计算与Sql Server中的键关联的值

时间:2017-06-09 06:45:42

标签: sql sql-server sql-server-2012

我有三张桌子

表类别

CategoryID         Category
1                   Climate
2                   Area

表类别详细信息

DetailID    CategoryID      Desc
1            1              Hot
2            1              Cold
3            2              Area1

表类别详细信息

PK  AnotherFK  CategoryDetailID
1    1           1
2    1           1
3    1           2
4    2           1

这里AnotherFK是引用另一个表的外键。在记录1和2中存在重复,但是AnotherFK 1引用了CategoryDe​​tailID 1和2,其categoryID为1,这是不正确的

所以从上面的表格 这个结果从以上三个表中有效

PK   AnotherFK    CategoryID  DetailID     Desc
1    1             1            1          Hot
2    1             1            1          Hot

但低于结果无效

PK   AnotherFK    CategoryID  DetailID     Desc
2    1             1           1           Hot
3    1             1           2           Cold

我不能将相同的AnotherFK放在两个具有相同CategoryID的不同DetailID中。我可以通过在CategoryDe​​tailValues表中引入CategoryID并创建唯一约束来消除这一点,但我不允许这样做。

现在我的目标是在CategoryDe​​tailValues表中查找具有与相同CategoryID相关联的不同DetailID的所有记录。这样我就可以删除它们了。

尝试在SQL Server 2012中实现此目的。

5 个答案:

答案 0 :(得分:0)

如果您的目标是突出显示具有相同CategoryID但不同的DetailID的所有AnotherFK案例,则以下应该执行此操作(伪代码):

SELECT * FROM (SELECT AnotherFK, ROW_NUMBER() OVER 
    (ORDER BY AnotherFK, CategoryID) AS rn FROM #myTable) AS a 
WHERE rn > 1

示例代码:

CREATE TABLE #myTable
(
  AnotherFK int
  , CategoryID int
  , DetailID int
  ) ;

  INSERT INTO #myTable (
  AnotherFK 
  , CategoryID 
  , DetailID 
  )
  VALUES (1, 1, 1)
  ,  (1, 1, 2);


  SELECT * FROM (SELECT AnotherFK, ROW_NUMBER() OVER (ORDER BY AnotherFK, CategoryID) AS rn FROM #myTable) AS a 
  WHERE rn > 1

  DROP TABLE #myTable

如果这不是你想要的,请详细说明

答案 1 :(得分:0)

我认为你可以使用这样的东西:

创建样本表的脚本:

CREATE TABLE mytable(
   PK               INTEGER  NOT NULL PRIMARY KEY 
  ,AnotherFK        INTEGER  NOT NULL
  ,CategoryDetailID INTEGER  NOT NULL
);
INSERT INTO mytable(PK,AnotherFK,CategoryDetailID) VALUES (1,1,1);
INSERT INTO mytable(PK,AnotherFK,CategoryDetailID) VALUES (2,1,1);
INSERT INTO mytable(PK,AnotherFK,CategoryDetailID) VALUES (3,1,2);
INSERT INTO mytable(PK,AnotherFK,CategoryDetailID) VALUES (4,2,1);
INSERT INTO mytable(PK,AnotherFK,CategoryDetailID) VALUES (5,1,3);
INSERT INTO mytable(PK,AnotherFK,CategoryDetailID) VALUES (6,1,3);
INSERT INTO mytable(PK,AnotherFK,CategoryDetailID) VALUES (7,1,3);

CREATE TABLE mytable2(
   DetailID   INTEGER  NOT NULL   
  ,CategoryID INTEGER  NOT NULL
  ,Descr       VARCHAR(5) NOT NULL
);

查询显示“可疑”记录(我认为你必须决定删除哪些记录......):

SELECT *  FROM (
SELECT * ,COUNT(*) OVER (PARTITION BY CategoryID, ANotherFK) AS X
, COUNT(*) OVER (PARTITION BY CategoryID, DetailID, ANotherFK) AS X1
FROM mytable A
INNER JOIN mytable2 B ON A.CategoryDetailID= B.DetailID
)C
WHERE X-X1 >0

输出:

+--+----+-----------+------------------+----------+------------+-------+---+----+
|  | PK | AnotherFK | CategoryDetailID | DetailID | CategoryID | Descr | X | X1 |
+--+----+-----------+------------------+----------+------------+-------+---+----+
|  |  1 |         1 |                1 |        1 |          1 | Hot   | 3 |  2 |
|  |  2 |         1 |                1 |        1 |          1 | Hot   | 3 |  2 |
|  |  3 |         1 |                2 |        2 |          1 | Cold  | 3 |  1 |
+--+----+-----------+------------------+----------+------------+-------+---+----+

答案 2 :(得分:0)

此查询将在Categorydetail中查找具有重复DetailID的记录。比加入表格为您提供详细信息。您仍然可以决定删除哪些记录。

select * 
from(
    Select CategoryID
    from CategoryDetail
    group by CategoryID
    having count(DetailID)>1)aggr
join CategoryDetail c on aggr.CategoryID = c.CategoryID
join CategoryDetailValues v on c.CategoryDetailID = v.CategoryDetailID

答案 3 :(得分:0)

你想要每个AnotherFK和Category一个值。所以第三个表应该有一个复合键:

  • CategoryDe​​tailValues(AnotherFK,CategoryID,DetailID,HowMany)

对AnotherFK,CategoryID具有唯一约束,并且都构建了CategoryDe​​tail(CategoryID,DetailID)的外键。

为了首先清理数据,你必须寻找含糊之处:

select AnotherFK, CategoryID, DetailID
from
(
  select 
    cdv.AnotherFK, cd.CategoryID, cdv.DetailID,
    count(distinct cd.DetailID) over (partition by cdv.AnotherFK, cd.CategoryID) as cnt
  from CategoryDetailValues cdv
  join CategoryDetail cd on cd.DetailID = cdv.CategoryDetailID
)
where cnt > 1
order by AnotherFK, CategoryID, DetailID

答案 4 :(得分:0)

您可以尝试以下假设的解决方案:within CDV table, for every [AnotherFK] value (ex. 1) should be displayed only those rows with the minimum [CategoryDetailID] (ex. 1)

SELECT *
FROM (
    SELECT cdv.PK, cdv.AnotherFK, cd.CategoryID, cd.[Desc],
        Rnk = DENSE_RANK() OVER(PARTITION BY cdv.AnotherFK ORDER BY cdv.CategoryDetailID)
    FROM dbo.CategoryDetailValues cdv
    JOIN dbo.CategoryDetail cd ON cd.DetailID = cdv.DetailID
    WHERE cdv.AnotherFK = 1
) x
WHERE x.Rnk = 1