我有两个连接在一起的表(在此示例中为Temp1和Temp2)。 Temp1中的某些ID具有链接到Temp2的多个ParentID,但我只希望实际返回1个ParentID。哪一个都不重要,所以我们只说Temp2中的最高值ID。
以下代码提供了一个很好的例子,说明了我从哪里开始
IF OBJECT_ID('tempdb..#Temp1') IS NOT NULL
DROP TABLE #Temp1
IF OBJECT_ID('tempdb..#Temp2') IS NOT NULL
DROP TABLE #Temp2
CREATE TABLE #Temp1
(
ID INT
,ParentID INT
,Name VARCHAR(10)
)
CREATE TABLE #Temp2
(
ID INT
,Name VARCHAR(15)
)
INSERT #Temp1 VALUES
(1, 1, 'Apples'),
(2, 1, 'Bananas'),
(3, 2, 'Milk'),
(3, 3, 'Milk'),
(4, 3, 'Wine'),
(4, 4, 'Wine')
INSERT #Temp2 VALUES
(1, 'Fruit'),
(2, 'Dairy'),
(3, 'Beverages'),
(4, 'Beer & Wine')
SELECT
T1.ID [ChildID]
,T1.Name [ChildName]
,T2.ID [ParentID]
,T2.Name [ParentName]
FROM #Temp1 T1
INNER JOIN #Temp2 T2 ON T2.ID = T1.ParentID
我想要的结果是:
ChildID ChildName ParentID ParentName
1 Apples 1 Fruit
2 Bananas 1 Fruit
3 Milk 3 Beverages
4 Wine 4 Beer & Wine
我还看到了其他这样的示例,人们在其中使用了CROSS APPLY,但我似乎无法使其正常工作。感谢您的协助!
答案 0 :(得分:1)
如下更改最终选择
;WITH CTE
AS
(
SELECT
RN = ROW_NUMBER() OVER(PARTITION BY T1.ID ORDER BY T1.Name),
T1.ID [ChildID]
,T1.Name [ChildName]
,T2.ID [ParentID]
,T2.Name [ParentName]
FROM #Temp1 T1
INNER JOIN #Temp2 T2 ON T2.ID = T1.ParentID
)
SELECT
[ChildID],
[ChildName],
[ParentID],
[ParentName]
FROM CTE
WHERE RN = 1
答案 1 :(得分:1)
一种方法是将#Temp2
表连接到cte,这是对#Temp1
进行逐组查询的结果,该表针对id和name的每种组合都包含一行,并带有min (或最大)父ID:
;WITH CTETemp1 AS
(
SELECT ID, Min(ParentID) As PID, Name
FROM #Temp1
GROUP BY ID, Name
)
SELECT T1.ID [ChildID]
,T1.Name [ChildName]
,T2.ID [ParentID]
,T2.Name [ParentName]
FROM CTETemp1 AS T1
JOIN #Temp2 AS T2 ON T1.PID = T2.ID
顺便说一句,这种关系被称为多对多关系,应该通过添加一个新表将#temp1
和#temp2
的ID链接在一起来实现它-这样看起来会更好像这样:
CREATE TABLE #Temp1
(
ID INT
,Name VARCHAR(10)
)
CREATE TABLE #Temp2
(
ID INT
,Name VARCHAR(15)
)
CREATE TABLE #Temp1ToTemp2
(
ID1,
ID2,
PRIMARY KEY(ID1, ID2)
)
INSERT #Temp1 VALUES
(1, 'Apples'),
(2, 'Bananas'),
(3, 'Milk'),
(4, 'Wine'),
INSERT #Temp2 VALUES
(1, 'Fruit'),
(2, 'Dairy'),
(3, 'Beverages'),
(4, 'Beer & Wine')
INSERT INTO #Temp1ToTemp2 (ID1, ID2) VALUES
(1,1), (2, 1), (3, 2), (3, 3), (4, 3), (4, 4)
主要优点是现在您的数据库中没有重复的数据了。
答案 2 :(得分:0)
您的结构破坏了数据库的正常形式。您显然具有多对多关系。我建议您重新设计表结构。就像您现在拥有的那样,表#Temp1
不在每一行中存储有关产品的信息,而是每行都呈现与#Temp2
的关系。
#Temp1
中的每个ID只能有一行。为简单起见,我省略了主键和外键约束:
CREATE TABLE #Temp1 (
ID INT,
Name VARCHAR(10)
)
CREATE TABLE #Temp2 (
ID INT,
Name VARCHAR(15)
)
CREATE TABLE #TempRelation (
ID_Temp1 INT,
ID_Temp2 INT
)
关键概念是将temp1和temp2之间的每个关系存储在单独的表#TempRelation
中。
要填充这些表,您需要将INSERT
语句更改为:
INSERT #Temp1 VALUES
(1, 'Apples'),
(2, 'Bananas'),
(3, 'Milk'),
(4, 'Wine')
INSERT #TempRelation VALUES
(1,1),
(2,1),
(3,2),
(3,3),
(4,3),
(4,4)
然后您的查询就这么简单:
SELECT
tr.id_temp1 as childid,
t1.name as childname,
tr.id_temp2 as parentid,
t2.name as parentname,
FROM (
SELECT id_temp1, max(id_temp2) as id_temp2
FROM #TempRelation tr
GROUP BY id_temp1
) tr
JOIN #Temp1 t1 ON tr.id_temp1 = t1.id
JOIN #Temp2 t2 ON tr.id_temp2 = t2.id