Mysql
 sql >> база данни >  >> RDS >> Mysql

Как да върнете набор от резултати въз основа на други редове

Ето две различни решения:(Забележка:нарекох полето за изброяване "package_type")

1-во решение (чрез функцията IF()):

select 
  i.location, 
  if(ps.id is not null, ps.id, pg.id) as package_id
from 
  (select distinct location from Items) i
  inner join 
    (select i.location, p.id
     from Items i
       inner join Packages p on (i.package_id = p.id and p.package_type = 'general')
    ) pg on (i.location = pg.location)
  left join 
    (select i.location, p.id
     from Items i
       inner join Packages p on (i.package_id = p.id and p.package_type = 'special')
    ) ps on (i.location = ps.location)

Това решение по същество взема местоположенията и го присъединява към пакета с general (за който се предполага, че съществува; следователно inner join ) и специален пакет (който е по избор; следователно left join ). Той създава записи като този:

location | general-package | [special-package]

След това използва MySQL IF функция, за да се опита първо да избере идентификатора на специален пакет и след това да се върне към общия идентификатор на пакета.

2-ро решение (чрез прехвърляне на enum към цяло число):

select i.location, p.id
from
  (select i.location, max(cast(package_type as unsigned)) as package_type
   from Items i
     left join Packages p on (i.package_id = p.id)
   group by location
  ) i
  inner join 
    (select i.location, p.id, p.package_type
     from Items i
       inner join Packages p on (i.package_id = p.id)
    ) p on (i.location = p.location and i.package_type = p.package_type)

Това решение използва факта, че изброяванията се съхраняват като цели числа. Прехвърля изброяването към цяло число. special в този случай ще върне 2 и general ще върне 1 . Тъй като тези специални в този случай гарантирано са по-високи от общите (т.е. 2> 1), можем да използваме MAX агрегатна функция. Сега по същество имаме таблица с местоположенията и техния „препоръчан пакет“ (т.е. специален, ако съществува, общ в противен случай). Просто присъединяваме това към нормалната заявка заедно с очаквания тип пакет и то връща правилните резултати.

Отказ от отговорност:Не съм сигурен за ефективността на нито един от тези методи, така че може да искате да тествате това сами.

Ако искате или да преработите таблицата, или да я денормализирате за ефективност, мисля, че този дизайн може да е по-подходящ:

GeneralPackages table
id, name
1, General Package 1

SpecialPackages table
id, name
1, Special Package 1
2, Special Package 2

Items table
id, general_package_id, special_package_id, location
1, 1, NULL, America
2, 1, 2, Europe

Предимството би било, че е по-лесно да се наложат няколко правила на ниво база данни:

  • Местоположението винаги трябва да има общ пакет (Items.general_package_id може да бъде дефиниран като НЕ NULL)
  • Местоположението трябва да има само един общ пакет (добавянето му в поле, а не в присъединяване гарантира, че има само един посочен)
  • Дано местоположение може да има най-много един специален пакет (добавянето му в поле, а не в присъединяване гарантира, че има само един посочен)
  • Външен ключ в Items.general_package_id =GeneralPackages.id ще гарантира, че тази колона съдържа само валидни пакети, които са „общи“.
  • Същото нещо може да се направи и за special_package_id.

Недостатъкът би бил, че вероятно ще трябва да използвате UNION ALL всеки път, когато използвате някоя от старите си заявки.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Какво е достатъчно дезинфекция за URL

  2. Писане на SQL заявка към SELECT елемент от следната таблица

  3. Не може да се създаде свързан сървър - sql сървър и mysql

  4. Съхранявайте HTML в MySQL база данни

  5. MySQL множествена логика WHERE И/OR