如何从msSQL中获取两条记录的通用值

时间:2011-09-05 07:02:08

标签: sql-server sql-server-2005

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 个答案:

答案 0 :(得分:2)

Revision1:我添加了一个精确划分的例子

操作被命名为关系分区。 在这种情况下,Table1(CatID,DealID)是被除数,Table2(CatID)是除数。 Table1(CatID, DealID) DIVIDED BY Table2(CatID)操作的结果(商)表示具有相同CatID(表2)的所有DealID(表1)。

对我来说,有些事情不是很清楚:你需要一个精确的分裂或一个剩下的分裂吗?

看看Joe Celko撰写的article

(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值生成标识符(表2b)。
  2. 基本查询将对来自被除数表(表1)的记录进行分组:GROUP BY a.DealID并且对于每个a.DealID值,它使用散列函数为CatID字段生成所有值的标识符:CHECKSUM_AGG( CHECKSUM(HASHBYTES('sha1',CAST(a.CatID AS VARCHAR(11)))) )。< / LI>

    风险:

    1. 有时,散列函数会产生冲突(尤其是旧的散列函数:CHECKSUM [_AGG])。
    2. 为了降低碰撞风险,我使用了HASHBYTES功能。
    3. 根据我的测试(不知何故,这个问题对我来说很老),我从未遇到过碰撞,但从不说永远不会
    4. 解决方案按“原样”提供,不提供任何担保。
    5. 如需生产,请使用Celko解决方案之一。

答案 1 :(得分:0)

试试这个(跳跃就是你需要的):

SELECT DealId, catId, count(catId) AS tot
FROM your_table
WHERE catId = your_cat1 OR catId = your_cat2
GROUP BY DealId
HAVING tot > 1

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我不明白你的问题,希望下面的语法帮助你。     CREATE PROCEDURE [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