SQL поиск строк, которые содержат несколько критериев - PullRequest
0 голосов
/ 14 мая 2009

у меня 3 стола

Customer
Groups
CustomerGroupJoins

поля, которые будут использоваться

Customer:Key
Groups:Key
CustomerGroupJoins:KeyCustomer, KeyGroup

Мне нужно найти всех пользователей во всех группах с ключами, 1,2,3

Я думал что-то вроде (но понятия не имею, правильный ли это / лучший путь):

SELECT 
  * 
FROM 
  Customer 
WHERE 
  Key = (
    SELECT KeyCustomer 
    FROM   CustomerGroupJoins 
    WHERE  KeyGroup = a
  ) = (
    SELECT KeyCustomer 
    FROM   CustomerGroupJoins 
    WHERE  KeyGroup = b
  ) = (
    SELECT KeyCustomer 
    FROM   CustomerGroupJoins 
    WHERE  KeyGroup = c
  )

Ответы [ 6 ]

2 голосов
/ 14 мая 2009

Я создал эти тестовые данные:

srh@srh@[local] =# select * from customer join customergroupjoins on customer.key = customergroupjoins.keycustomer join groups on groups.key = customergroupjoins.keygroup;
 key |  name  | keycustomer | keygroup | key |  name   
-----+--------+-------------+----------+-----+---------
   1 | fred   |           1 |        1 |   1 | alpha
   1 | fred   |           1 |        2 |   2 | beta
   1 | fred   |           1 |        3 |   3 | gamma
   2 | jim    |           2 |        1 |   1 | alpha
   2 | jim    |           2 |        2 |   2 | beta
   2 | jim    |           2 |        4 |   4 | delta
   2 | jim    |           2 |        5 |   5 | epsilon
   3 | shelia |           3 |        1 |   1 | alpha
   3 | shelia |           3 |        3 |   3 | gamma
   3 | shelia |           3 |        5 |   5 | epsilon
(10 rows)

Таким образом, "Фред" является единственным клиентом во всем (альфа, бета, гамма). Чтобы определить, что:

srh@srh@[local] =# select * from customer
  where exists (select 1 from customergroupjoins where keycustomer = customer.key and keygroup = 1)
  and exists (select 1 from customergroupjoins where keycustomer = customer.key and keygroup = 2)
  and exists (select 1 from customergroupjoins where keycustomer = customer.key and keygroup = 3);
 key | name 
-----+------
   1 | fred
(1 row)

Это один из подходов. (1,2,3) - ваши известные групповые ключи - это параметры в подзапросах. Кто-то уже упоминал, что вам вообще не нужно присоединяться к таблице групп.

Другой способ:

select customer.*
from customer
  join customergroupjoins g1 on g1.keycustomer = customer.key
  join customergroupjoins g2 on g2.keycustomer = customer.key
  join customergroupjoins g3 on g3.keycustomer = customer.key
where g1.keygroup = 1 and g2.keygroup = 2 and g3.keygroup = 3

Общая проблема поиска пользователей во всех группах (g_1, g_2 .. g_N) немного сложнее. Указанные выше запросы объединяются в таблицу ссылок (customergroupjoins) N раз, поэтому это разные запросы в зависимости от количества групп, с которыми вы проверяете.

Один из подходов к , который заключается в создании временной таблицы для использования в качестве параметра запроса: таблица содержит список групп, которые должны быть у всех клиентов. Так, например, создайте временную таблицу с именем «ParamGroups» (или «#ParamGroups» на SQL Server, чтобы пометить ее как временную), заполните ее интересующими вас групповыми ключами и затем сделайте следующее:

select * from customer where key in (
    select keycustomer
    from customergroupjoins
      join paramgroup on paramgroup.keygroup = customergroupjoins.keygroup
    group by keycustomer
    having count(*) = (select count(*) from paramgroup))

Также, как новичок, я настоятельно рекомендую вам ознакомиться с советами по соглашениям об именах для таблиц и столбцов базы данных. У всех разные идеи (и они могут зажечь священные войны), но выберите некоторые стандарты (если они вам не продиктованы) и придерживайтесь их. Например, вы назвали одну таблицу «customer» (единственное число) и одну таблицу «groups» (множественное число), что выглядит плохо. Более обычно использовать «id» вместо «key» и использовать его в качестве суффикса («customer_id» или «CustomerID»), а не префикса. Весь аргумент CamelCase против old_skool - это больше вопрос стиля, как и первичный ключ-это-просто-id-not-table_id.

1 голос
/ 14 мая 2009

Вышеуказанные решения будут работать, если клиент входит в любую из трех групп, но не проверяет членство в всех из них.

Попробуйте вместо этого:

SELECT  a.*
FROM    (SELECT c.*, substring((SELECT      (', ' + cg.KeyGroup)
                                FROM        CustomerGroupJoins cg
                                WHERE       cg.KeyCustomer = c.[Key]
                                AND         cg.KeyGroup IN (1,2,3)
                                ORDER BY    cg.KeyGroup ASC
                                FOR XML PATH('')), 3, 2000) AS GroupList
        FROM    Customer AS c) AS a
WHERE   a.GroupList = ('1, 2, 3')

Это также будет работать:

SELECT  c.*
FROM    Customer c
WHERE   c.[Key] IN  (SELECT     cg.[KeyGroup]
                    JOIN        CustomerGroupJoins cg                       WHERE       cg.KeyGroup IN (1,2,3)
                    GROUP BY    cg.KeyGroup
                    HAVING      count(*) = 3)
0 голосов
/ 14 мая 2009

Вот возможный ответ, не проверенный:

select custid
from CustomerGroupJoins
where groupid in (1,2,3)
group by custid
having count(*) = 3

Выполняет поиск клиентов, у которых есть 3 строки с groupid 1, 2 или 3. Это означает, что они находятся во всех 3 группах, поскольку я предполагаю, что у вас включен первичный ключ (custid, groupid).

0 голосов
/ 14 мая 2009
SELECT *
  FROM customer c
    INNER JOIN customerGroupJoins j ON(j.customerKey = c.key)
  WHERE j.keyGroup IN (1, 2, 3)

Вам не нужно объединяться с таблицей групп, если вас интересует только ключ группы, который находится в вашей таблице соединений.

0 голосов
/ 14 мая 2009

Из того, что вы описали, попробуйте это:

SELECT * FROM Customer c
INNER JOIN CustomerGroupJoins cgj
ON c.key = cgj.keyCustomer
INNER JOIN groups g
ON cgj.keyGroup = g.key
WHERE g.key IN (1,2,3)
0 голосов
/ 14 мая 2009

Может как то так?

SELECT c.Key, g.Key, cgj.KeyCustomer, cgj.KeyGroup
FROM Customer c
LEFT JOIN CustomerGroupJoins cgj ON cgj.KeyCustomer = c.Key
LEFT JOIN Groups g ON g.Key = cgj.KeyGroup
WHERE g.key IN (1, 2, 3)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...