[Помощь] Подсчет строк по условию (см. внутри)

Тема в разделе "Базы данных", создана пользователем Genk0, 20 апр 2014.

Статус темы:
Закрыта.
Модераторы: latteo
  1. Genk0

    Genk0 Инквизитор из раздела J!

    Moderator
    Регистр.:
    2 июн 2010
    Сообщения:
    1.645
    Симпатии:
    1.349
    Таблица категорий - categories
    id, pid
    id - понятно
    pid - id родительской категории (если это подкатегория 2 или 3 уровня) или 0, если это первый уровень категории.


    Таблица объявлений - items
    cat_id1, cat_id2, cat_id3, cat_id, city_id
    cat_id1 - id родительской категории
    cat_id2 - id категории 2 уровня
    cat_id3 - id категории 3 уровня или значение 0 , если третьего уровня не указано.
    cat_id - id категории последнего уровня. Допустим указаны cat_id1 = 20, cat_id2 = 23, cat_id = 0, то в cat_id ,будет 23.
    city_id - id города


    Нужно посчитать количество объявлений в каждой категории учитывая город объявления.
    Считать: 1 уровень - все объявления в подкатегориях - 1,2,3 уровня. 2 уровень - все объявления в категориях 2 и 3 уровня. 3 уровень считать не нужно.

    Туплю не первый день, устал. Спасайте :thenks:
     
  2. DesoTTo

    DesoTTo Создатель

    Регистр.:
    21 дек 2012
    Сообщения:
    48
    Симпатии:
    12
    С утром!

    А платформа какая SQL? MySQL? Ora?

    И тебе на выходе нада типа:
    город(id) | 1ур. | 2ур.
    Махачкала 130 78
    Крым 300 213
    ?

    Категории всегда на одном уровне? cat_id1, cat_id2, cat_id3, cat_id в items не противоречит связке id<->pid в categories?

    На первый взгляд проще всего перед вызовом запроса определять уровень категории и тупо суммировать потом с группировкой по соответствующему cat_id*...
     
  3. Genk0

    Genk0 Инквизитор из раздела J!

    Moderator
    Регистр.:
    2 июн 2010
    Сообщения:
    1.645
    Симпатии:
    1.349
    mysql,
    Нужно посчитать количество объявлений в каждой категории учитывая город объявления.
    На сайте выбран город МСК, значит запрос в БД пошел с параметров where city_id = 3 (МСК)
    Транспорт - 10 объявлений (1 уровень) : Авто - 4 (2 уровень), Мото - 6 (2 уровень).

    Items:
    cat_id1 - категория 1 уровня данного объявления
    cat_id2 - категория 2 уровня данного объявления
    cat_id3 - категория 3 уровня данного объявления, может быть указано 0, если объвяление находится максимум во втором уровне категорий.
    cat_id - дублирует последний id (уровня категорий)
    Например: Продам ВАЗ - cat_id1 =20, cat_id2=17,cat_id3=0,cat_id=17
    Categories:
    id - ИД категории, pid - если эта категория является подкатегорией, то указывается id категории выше уровнем.
    Транспорт (1 ур.) - id=50, pid=0
    Авто(2 ур.) - id=48, pid=50
    Мото(2 ур.) - id=47, pid=50
     
  4. DesoTTo

    DesoTTo Создатель

    Регистр.:
    21 дек 2012
    Сообщения:
    48
    Симпатии:
    12
    Как-то так должно работать
    Код:
    select * from (
    SELECT
    items.city_id,
    count(*) as qty
    FROM items where items.cat_id1 = cat_id_param
    group by items.city_id
    union
    SELECT
    items.city_id,
    count(*)
    FROM items where items.cat_id2 = cat_id_param
    group by items.city_id
    union
    SELECT
    items.city_id,
    count(*)
    FROM items where items.cat_id3 = cat_id_param
    group by items.city_id
    ) where city_id = city_id_param;
    
    Но это ппц колхоз :)
    Что то от такой структуры голова раком и мне кажется можно проще всё вязать изначально было. Надеюсь если даже и не помог то хоть куда копать прояснил немного...
     
    Последнее редактирование модератором: 21 апр 2014
  5. Genk0

    Genk0 Инквизитор из раздела J!

    Moderator
    Регистр.:
    2 июн 2010
    Сообщения:
    1.645
    Симпатии:
    1.349
    что за cat_id_param ?! откуда он взялся?!
    Структура такая у разработчика одного.. скрипта.. чтобы поменять локику... да лучше запрос составить на подсчет, чем переписать это все.
     
  6. latteo

    latteo Эффективное использование PHP, MySQL

    Moderator
    Регистр.:
    28 фев 2008
    Сообщения:
    1.517
    Симпатии:
    1.368
    Мда, как то всё запутано...
    1) поправлю вариант постом выше, вариант показывает количество объявлений для известных city_id, cat_id1, cat_id2, cat_id3
    Код:
    SELECT city_id, cat_id1, count(*)	FROM bbs_items WHERE city_id = 18 AND bbs_items.cat_id1 = 77
    UNION ALL
    SELECT city_id, cat_id2, count(*)	FROM bbs_items WHERE city_id = 18 AND bbs_items.cat_id2 = 92
    UNION ALL
    SELECT city_id, cat_id3, count(*)	FROM bbs_items WHERE city_id = 18 AND bbs_items.cat_id3 = 195
    
    2) Нам известен только city_id надо посчитать количество объявлений во всём многообразии категорий, которые могут быть для этого города:
    Код:
    SELECT bbs_items.city_id, bbs_items.cat_id1, bbs_categories.title_ru, count(bbs_items.id)
    	FROM bbs_items, bbs_categories WHERE bbs_items.city_id = 17 AND bbs_items.cat_id1 = bbs_categories.id
    	group by bbs_items.cat_id1
    UNION ALL
    SELECT bbs_items.city_id, bbs_items.cat_id2, bbs_categories.title_ru, count(bbs_items.id)
    	FROM bbs_items, bbs_categories WHERE bbs_items.city_id = 17 AND bbs_items.cat_id2 = bbs_categories.id
    	group by bbs_items.cat_id2
    UNION ALL
    SELECT bbs_items.city_id, bbs_items.cat_id3, bbs_categories.title_ru, count(bbs_items.id)
    	FROM bbs_items, bbs_categories WHERE bbs_items.city_id = 17 AND bbs_items.cat_id3 = bbs_categories.id AND bbs_items.cat_id3 <> 0
    	group by bbs_items.cat_id3
    
     
    DesoTTo нравится это.
  7. DesoTTo

    DesoTTo Создатель

    Регистр.:
    21 дек 2012
    Сообщения:
    48
    Симпатии:
    12
    Это параметр обозначил , категории и города. Собственно сперва считаешь все, потом фильтруешь что нужно по id города. Иначе пока идей нет.

    latteo, сорри, как год под рукой нет практики, отвык несколько, буду впредь корректней писать, заодно и вспомним), А так на твой взгляд только юнион возможен,или кейс можно обыграть попробовать? А то несколько громоздко всё равно, кмк.
     
    Последнее редактирование модератором: 21 апр 2014
  8. latteo

    latteo Эффективное использование PHP, MySQL

    Moderator
    Регистр.:
    28 фев 2008
    Сообщения:
    1.517
    Симпатии:
    1.368
    Как через case обыграть я не представляю, но я этим оператором в Mysql особо и не пользуюсь.
    А вообще изначально я хотел через JOIN, но излишне увлёкся Union и вот только теперь сообразил более компактную запись:
    Код:
    SELECT c.title_ru, COUNT(i.id) FROM `bbs_categories` as c
    JOIN bbs_items as i ON c.id = i.cat_id1 OR c.id = i.cat_id2 OR c.id = i.cat_id3
    WHERE i.city_id = 17
    GROUP BY c.id
    
     
    Umid и Genk0 нравится это.
Статус темы:
Закрыта.