Как получить общее значение для двух записей из msSQL - PullRequest
0 голосов
/ 05 сентября 2011
catId  DealId
 1      668
 2      668
 3      669
 1      669
 3      671
11      671
12      671
 7      669
12      672
13      673

Предположим, это стол. Если я введу два значения для catId в качестве входных данных, запрос должен вернуть все записи, содержащие одинаковые DealId.

Ответы [ 4 ]

2 голосов
/ 05 сентября 2011

Revision1: я добавил пример для точного деления

Эта операция называется реляционным делением.В этом случае Table1 (CatID, DealID) является дивидендом, а Table2 (CatID) является делителем.Результат (частное) операции Table1(CatID, DealID) DIVIDED BY Table2(CatID) представляет все DealIDs (Таблица1), которые имеют одинаковые CatID (Таблица2).

Что-то не очень понятно для меня: вам нужно точное деление или деление с остатком?

Взгляните на эту статью , написанную Джо Селко.

(Revision1) Пример для точного деления (мои значения из таблицы (CatID, DealID) отличаются; объяснения и риски представлены ниже):

DECLARE @Table1 TABLE
(
    DealID INT NOT NULL
    ,CatID INT NOT NULL
    ,PRIMARY KEY(DealID, CatID)
);
INSERT  @Table1 (DealID, CatID)
SELECT  src.DealID, src.CatID
FROM
(
SELECT 1 CatID, 668 DealID
UNION ALL
SELECT 2 CatID, 668 DealID
UNION ALL
SELECT 2 CatID, 669 DealID
UNION ALL
SELECT 1 CatID, 669 DealID
UNION ALL
SELECT 2 CatID, 671 DealID
UNION ALL
SELECT 11 CatID, 671 DealID
UNION ALL
SELECT 12 CatID, 671 DealID
UNION ALL
SELECT 11 CatID, 672 DealID
UNION ALL
SELECT 12 CatID, 672 DealID
UNION ALL
SELECT 13 CatID, 673 DealID
) src;

--Test1
DECLARE @Table2 TABLE
(
    CatID INT NOT NULL PRIMARY KEY
);
INSERT  @Table2 
VALUES  (1);
INSERT  @Table2 
VALUES  (2);

SELECT  CatID, DealID
FROM    @Table1
ORDER BY DealID;
SELECT  *
FROM    @Table2
ORDER BY CatID;

SELECT  a.DealID--, CHECKSUM_AGG( CHECKSUM(HASHBYTES('sha1',CAST(a.CatID AS VARCHAR(11)))) ) Agg
FROM    @Table1 a
GROUP BY a.DealID 
HAVING  CHECKSUM_AGG( CHECKSUM(HASHBYTES('sha1',CAST(a.CatID AS VARCHAR(11)))) ) = 
(
    SELECT  CHECKSUM_AGG( CHECKSUM(HASHBYTES('sha1',CAST(b.CatID AS VARCHAR(11)))) ) 
    FROM    @Table2 b
);
--End of Test1

--Test2
DELETE @Table2;
INSERT  @Table2 
VALUES  (11);
INSERT  @Table2 
VALUES  (12);

SELECT  a.DealID--, CHECKSUM_AGG( CHECKSUM(HASHBYTES('sha1',CAST(a.CatID AS VARCHAR(11)))) ) Agg
FROM    @Table1 a
GROUP BY a.DealID 
HAVING  CHECKSUM_AGG( CHECKSUM(HASHBYTES('sha1',CAST(a.CatID AS VARCHAR(11)))) ) = 
(
    SELECT  CHECKSUM_AGG( CHECKSUM(HASHBYTES('sha1',CAST(b.CatID AS VARCHAR(11)))) ) 
    FROM    @Table2 b
);
--End of Test2

Пояснения:

  1. Этот подзапрос SELECT CHECKSUM_AGG( CHECKSUM(HASHBYTES('sha1',CAST(b.CatID AS VARCHAR(11)))) ) FROM @Table2 b генерирует идентификатор для всех значений CatID из таблицы делителей (Таблица2 b).
  2. Базовый запрос будет группировать записи из таблицы дивидендов (Таблица1 a): GROUP BY a.DealID и дляКаждое значение a.DealID генерирует идентификатор для всех значений из поля CatID с использованием хеш-функций: CHECKSUM_AGG( CHECKSUM(HASHBYTES('sha1',CAST(a.CatID AS VARCHAR(11)))) ).

Риски:

  1. Иногда хеш-функции могут генерироватьколлизии (особенно старые хеш-функции: CHECKSUM [_AGG]).
  2. Чтобы уменьшить риск коллизий, я использую функцию HASHBYTES.
  3. Из моих тестов (почему-то эта проблема для меня старая),Я никогда не сталкивался с коллиsions но никогда не говори никогда .
  4. РЕШЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ» БЕЗ ГАРАНТИИ.
  5. Для производства используйте одно из решений Celko.
0 голосов
/ 05 сентября 2011

Я не понимаю ваш вопрос, надеюсь, вам поможет следующий синтаксис.ПРОЦЕДУРА СОЗДАНИЯ [spName]

    @Parameter1 INT,
    @Parameter2 INT

AS 
    BEGIN              

        SELECT * FROM TableName WHERE 
        DealId    FROM    TableName WHERE catId=@Parameter1
        AND 
        DealId    FROM    TableName WHERE catId=@Parameter2
     END
0 голосов
/ 05 сентября 2011

SQL-оператор

;WITH CatIDs (catID) AS (
    SELECT  1
    UNION ALL SELECT 2
)   
SELECT  mt.*
FROM    MyTable mt
        INNER JOIN CatIDs cid ON cid.catID = mt.catID
        INNER JOIN (
            SELECT  mt.DealID
            FROM    MyTable mt
                    INNER JOIN CatIDs ids ON ids.catID = mt.catID
            GROUP BY
                    mt.DealID
            HAVING  COUNT(mt.DealID) = (SELECT COUNT(*) FROM CatIDs)
        ) did ON did.DealID = mt.DealID

Тестовый скрипт

;WITH MyTable (catID, DealID) AS (
    SELECT 1, 668
    UNION ALL SELECT 2, 668
    UNION ALL SELECT 3, 669
    UNION ALL SELECT 1, 669
    UNION ALL SELECT 3, 671
    UNION ALL SELECT 11, 671
    UNION ALL SELECT 12, 671
    UNION ALL SELECT 7, 669
    UNION ALL SELECT 12, 672
    UNION ALL SELECT 13, 673
)
, CatIDs (catID) AS (
    SELECT  1
    UNION ALL SELECT 2
)   
SELECT  mt.*
FROM    MyTable mt
        INNER JOIN CatIDs cid ON cid.catID = mt.catID
        INNER JOIN (
            SELECT  mt.DealID
            FROM    MyTable mt
                    INNER JOIN CatIDs ids ON ids.catID = mt.catID
            GROUP BY
                    mt.DealID
            HAVING  COUNT(mt.DealID) = (SELECT COUNT(*) FROM CatIDs)
        ) did ON did.DealID = mt.DealID
0 голосов
/ 05 сентября 2011

Попробуйте (прыгайте, это то, что вам нужно):

SELECT DealId, catId, count(catId) AS tot
FROM your_table
WHERE catId = your_cat1 OR catId = your_cat2
GROUP BY DealId
HAVING tot > 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...