Застрял в группе - PullRequest
0 голосов
/ 28 мая 2009
table 1 - 
pid cid
901 101
901 102
901 103
902 102
902 105
903 105

table 2 -
cid
101
102
105

Мне нужно, чтобы Pid из таблицы1 отображался ТОЛЬКО, если ВСЕ CID соответствуют CID из таблицы 2. Это означает, что в случае 901, который имеет CID 101,102 и 103, НЕ должен отображаться в операторе выбора, причина 103 не существует в таблице 2.

Ответы [ 10 ]

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

Я предполагаю, что вам нужен только PID, а также что CID не является отрицательным. Тогда

Решение: (версия без COUNT (..) и EXIST (..))

SELECT      table1.pid
FROM        table1
LEFT JOIN   table2 ON table1.cid = table2.cid
GROUP BY    table1.pid
HAVING      MIN(COALESCE(table2.cid, -1)) <> -1

возвращается:

pid
-----------
902
903
1 голос
/ 28 мая 2009

Попробуйте следующее, возможно, это поможет вам в правильном направлении.

Таким образом вы получите все идентификаторы PID в таблице 1, у которых все идентификаторы CID расположены в таблице 2

.

Из того, что было получено из вопроса, PID в таблице 1 не обязательно должны иметь все CID в таблице 2, он просто должен иметь CID, которые находятся в таблице 2, и если один из его 'CID не в таблице 2, тогда PID становится недействительным.

DECLARE @table1 TABLE   (
                        pid INT,
                        cid INT
                        )

DECLARE @table2 TABLE   (
                        cid INT
                        )

INSERT  @table1
SELECT  901, 101 UNION ALL
SELECT  901, 102 UNION ALL
SELECT  901, 103 UNION ALL
SELECT  902, 102 UNION ALL
SELECT  902, 105 UNION ALL
SELECT  903, 105

INSERT  @table2
SELECT  101 UNION ALL
SELECT  102 UNION ALL
SELECT  105

DECLARE @temp TABLE (
                    pid     INT,
                    cid     INT,
                    test    INT
                    )

INSERT      @temp
SELECT      a.pid,
            a.cid,
            b.pid
FROM        @table1 a
LEFT JOIN   (
            SELECT      t1.pid,
                        t1.cid
            FROM        @table1 t1
            LEFT JOIN   @table2 t2
                    ON  t1.cid = t2.cid
            WHERE       t2.cid IS NULL
            ) b
        ON  a.pid = b.pid
        AND a.cid = b.cid

-- Compare the counts of nulls
SELECT      a.pid
FROM        (
            SELECT      pid,
                        COUNT(1) AS cnt
            FROM        @temp
            GROUP BY    pid
            ) a
INNER JOIN  (
            SELECT      pid,
                        COUNT(1) AS cnt
            FROM        @temp
            WHERE       test IS NULL
            GROUP BY    pid
            ) b
        ON  a.pid = b.pid
        AND a.cnt = b.cnt
0 голосов
/ 28 мая 2009

Я специально не использую sql / tsql, но я думаю, что решение в mysql заключается в следующем, возможно, кто-то может перевести его в sql / tsql, так как я думаю, что это простое решение проблемы.

SELECT
    count(t2.cid IS NULL) AS noMatch
        ,pid
    FROM table1       t1
    LEFT JOIN table2  t2 ON t2.cid = t1.cid
    HAVING noMatch = 0;
0 голосов
/ 28 мая 2009

Если я вас правильно понимаю, ваша цель - получать строки только там, где нет ни одного непревзойденного cid - то есть, если есть хотя бы одна строка с таким же pid и несуществующим cid, не показывать строки с этим пидом. Если это так, то самый простой способ его кодирования - это использовать в той же таблице, например:

SELECT * 
  FROM 
    [table 1] T1A 
  WHERE 
    /* there are no rows in my same table ... */
    NOT EXISTS (
        SELECT * 
          FROM 
            [table 1] T1B 
          WHERE 
            T1A.pid = T1B.pid 
            /* ... that do not have a matching cid in table 2 */
            AND T1B.cid NOT IN (SELECT cid FROM [table 2])
    )

Возвращает 3 строки с pid = 902 и ни одной из строк с pid = 901.

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

Итак, вам нужны идентификаторы PID из таблицы1, в которых нет пары (PID, CID) в таблице1, поэтому PID отсутствует в таблице2.

select pid from (select distinct pid from table1) table1_pids
where not exists (select 1 from table1 where table1.pid = table1_pids.pid
            and not exists (select 1 from table2 where table2.cid = table1.cid));

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

select pid from table1 left join table2 on table1.cid = table2.cid
group by pid
having sum(case when table2.cid is null then 1 else 0 end) = 0
0 голосов
/ 28 мая 2009

Нет необходимости использовать вложенный запрос, быстрее сделать естественное соединение. Не уверен, какой тип базы данных вы используете, но она все равно должна работать. Нужен только отчет, если вы хотите вернуть каждый правильный pid только один раз.

SELECT DISTINCT t1.pid
FROM   table1 t1, table2 t2
WHERE  t1.cid = t2.cid
0 голосов
/ 28 мая 2009

Я верю, что вы ищете что-то вроде этого:

Select distinct pid
from table1 t1
  join table2 on t1.cid = table2.cid
group by pid
having count(t1.cid) = (select count(cid) from table1 where pid = t1.pid)
0 голосов
/ 28 мая 2009

Как насчет

SELECT DISTINCT PID --Get all the other PIDS
FROM Table1
WHERE PID NOT IN
(
    SELECT PID --Get the PIDS From Table 1 That Have a CID NOT IN Table2
    FROM Table1 
    WHERE CID NOT IN (
        SELECT CID    --Get All The Table 2 CIDs
        FROM Table2 
    )
)
0 голосов
/ 28 мая 2009

Я интерпретирую ваш вопрос так, что вы хотите получить список pid с Table1, в котором каждый cid соответствует Table2. Другими словами, в следующем примере 901 совпадают, но 902, 903 и 904 не совпадают:

 Table1             Table2
pid | cid          cid
---------          ----
901 | 100          100
901 | 101          101
902 | 101
903 | 100
903 | 105
904 | 100
904 | 101
904 | 105

Вот запрос:

DECLARE @NUM_CIDS INT
SELECT @NUM_CIDS = COUNT(1) FROM Table2

SELECT Table1.pid
FROM Table1
INNER JOIN Table2
ON Table1.cid = Table2.cid
GROUP BY Table1.pid
HAVING COUNT(Table2.cid) = @NUM_CIDS

Он работает путем объединения двух таблиц, а затем возвращает только pid с правильным числом cid с. Он гарантированно работает, поскольку, если запись в Table1 не совпадает, она не будет участвовать в объединении. И если pid не завершен, он будет отклонен предложением HAVING.

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

попробуйте это:

DECLARE @table1 table (pid int, cid int)
DECLARE @table2 table (cid int)

INSERT INTO @table1 VALUES (901,101)
INSERT INTO @table1 VALUES (901,102)
INSERT INTO @table1 VALUES (901,103)
INSERT INTO @table1 VALUES (902,102)
INSERT INTO @table1 VALUES (902,105)
INSERT INTO @table1 VALUES (903,105)

INSERT INTO @Table2 VALUES (101)
INSERT INTO @Table2 VALUES (102)
INSERT INTO @Table2 VALUES (105)

SELECT
    dt.pid
    FROM (SELECT
              t1.pid, t2.cid
              FROM @table1                 t1
                  LEFT OUTER JOIN @table2  t2 ON t1.cid=t2.cid
         ) dt
    GROUP BY dt.pid
    HAVING COUNT(dt.pid)=COUNT(dt.cid)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...