2016-09-21 42 views
0
A27,346467413,68723601 
A28,346467414,68723601 
A28,346467416,68723601 
A27,349454768,8908697809 
A28,349454769,8908697809 
A28,349454771,8908697809 

我从上面的示例表中我需要做一些令人难以置信的SQL上。基本上,我问到的是,对于每个A27,两个程序A28属于A27,并且需要将信息连接在一起。然而,我被要求为每个A_Number创建一个表,所以A27将在它自己的表中,A28将在它自己的表中。我需要做的是在他们身上做一个Join,这样每个A27都可以链接到它后面相应的A28。只是想知道如果它在单独的表格中以及Join和SQL的外观如何,我会怎么做?请记住,非数据与其发票调节有关。引用完整性和复杂的连接

enter image description here

我已经上传样本文件附

enter image description here

+0

有点混乱请张贴预期输出并提及列名称。 – Susang

+0

从描述中可以看出,表格数据中除了邻近关系之外,没有任何关联父母(A27)和子女(A28)。在Oracle中,数据检索是非确定性的 - 数据检索的顺序将会更改,除非您指定顺序。您没有可用于订购的钥匙,因此会成为问题。也许SQL Server是不同的。 –

+0

假设你*可以*可靠地将父母连接到孩子,那么你需要为每个父母分配一个ID并在孩子身上引用它。将数据插入到两个表中,并且加入是微不足道的 –

回答

1
;WITH cte AS (
    SELECT 
     * 
     ,ROW_NUMBER() OVER (ORDER BY Column2) AS RowNumber 
    FROM 
     @Table 
) 

SELECT 
    * 
    ,DENSE_RANK() OVER (ORDER BY A27.Column2) as GroupingId 
FROM 
    cte A27 
    LEFT JOIN cte A28 
    ON A28.RowNumber IN (a27.RowNumber + 1, a27.RowNumber + 2) 
    AND A28.Column1 = 'A28' 
WHERE 
    A27.Column1 = 'A27' 

因为根据您的图像Column3不是唯一的只有你想要的行号我没有去使用它的路线。相反,我使用了基于Column2ROW_NUMBER,这似乎是一个增量主键,然后是LEFT SELF JOIN。这是针对每个A27行的2个A28行AFTER。如果你想“preceding”喜欢你的OP说,但当时并没有建议通过简单地改变JOIN条件扭转这种局面:

ON A28.RowNumber IN (a27.RowNumber - 1, a27.RowNumber - 2) 

注意我添加了GroupingID给你的方式识别其中A27和A28的是它们可以一起用作A27表中的新主键和A28表中的外键以保持关系。

这是我使用的测试数据。

DECLARE @Table AS TABLE (Column1 CHAR(3), Column2 BIGINT, Column3 BIGINT) 
INSERT INTO @Table VALUES 
('A27',346467408,68723601) 
,('A28',346467409,68723601) 
,('A28',346467411,68723601) 
,('A27',346467413,68723601) 
,('A28',346467414,68723601) 
,('A28',346467416,68723601) 
,('A27',349454768,8908697809) 
,('A28',349454769,8908697809) 
,('A28',349454771,8908697809) 

编辑:根据您如何做时,在单独的表评论。您可以使用UNION ALL组合表格:

DECLARE @A27 AS TABLE (Column1 CHAR(3), Column2 BIGINT, Column3 BIGINT) 
DECLARE @A28 AS TABLE (Column1 CHAR(3), Column2 BIGINT, Column3 BIGINT) 
INSERT INTO @A27 VALUES 
('A27',346467408,68723601) 
,('A27',346467413,68723601) 
,('A27',349454768,8908697809) 
INSERT INTO @A28 VALUES 
('A28',346467409,68723601) 
,('A28',346467411,68723601) 
,('A28',346467414,68723601) 
,('A28',346467416,68723601) 
,('A28',349454769,8908697809) 
,('A28',349454771,8908697809) 

;WITH cteUnion AS (
    SELECT 
     Column1, Column2, Column3 
    FROM 
     @A27 

    UNION ALL 

    SELECT 
     Column1, Column2, Column3 
    FROM 
     @A28 
) 

, cteRowNum AS (
    SELECT * ,ROW_NUMBER() OVER (ORDER BY Column2) AS RowNumber 
    FROM 
     cteUnion 
) 

SELECT *, DENSE_RANK() OVER (ORDER BY a27.Column2) as GroupingId 
FROM 
    cteRowNum a27 
    LEFT JOIN cteRowNum a28 
    ON a28.RowNumber IN (a27.RowNumber + 1, a27.RowNumber + 2) 
    AND a28.Column1 = 'A28' 
WHERE 
    a27.Column1 = 'A27' 

如果表是较大的或者表现可能是你可能想建立一个临时表,这样做的一个问题。

IF OBJECT_ID('tempdb..#Combined') IS NOT NULL 
    BEGIN 
     DROP TABLE #Combined 
    END 

CREATE TABLE #Combined (
    TableName CHAR(3) 
    ,Column2 BIGINT 
) 

INSERT INTO #Combined (TableName, Column2) 
SELECT Column1, Column2 
FROM 
    @A27 

INSERT INTO #Combined (TableName, Column2) 
SELECT Column1, Column2 
FROM 
    @A28 

;WITH cteRowNum AS (
    SELECT * ,ROW_NUMBER() OVER (ORDER BY Column2) AS RowNumber 
    FROM 
     #Combined 
) 

SELECT *, DENSE_RANK() OVER (ORDER BY a27.Column2) as GroupingId 
FROM 
    cteRowNum a27 
    LEFT JOIN cteRowNum a28 
    ON a28.RowNumber IN (a27.RowNumber + 1, a27.RowNumber + 2) 
    AND a28.TableName = 'A28' 
WHERE 
    a27.TableName = 'A27' 
+0

谢谢马特,这确实帮助很多,我试图复制你已经做了,但A28和A27的价值分别在他们自己的表中,所以我似乎无法得到正确的结果时,你有两个查询两个表。你会怎么做呢? – abs786123

+0

@ abs786123您可以使用union all并合并表或临时表。我已经更新了答案。如果答案满足您的需求,请将其标记为已接受,以便其他人知道您有解决方案并授予声望点。谢谢 – Matt

+0

再次感谢Matt,如果表a27和a28中的列在请求显示的列中有不同的数据类型。任何方式作为上述两个将取决于数据类型是相同的结果集? – abs786123

1

最佳猜测给出缺少格式化输出...

  • 我用了一个CTE(公共表表达式)对于数据集,并且为每个集合生成行号。
  • 我用左连接,因为我不知道是否总会有3行。
  • 我认为col3是每个组/分区的唯一标识符。
  • 我认为col2值对于A27总是最低的。
  • 我使用ROW_NUMBER与数的行的每个分区

WITH dataset as (
SELECT 'A27' as Col1,346467413 as col2,68723601 as col3 UNION ALL 
SELECT 'A28' as Col1,346467414 as col2,68723601 as col3 UNION ALL 
SELECT 'A28' as Col1,346467416 as col2,68723601 as col3 UNION ALL 
SELECT 'A27' as Col1,349454768 as col2,8908697809 as col3 UNION ALL 
SELECT 'A28' as Col1,349454769 as col2,8908697809 as col3 UNION ALL 
SELECT 'A28' as Col1,349454771 as col2,8908697809 as col3), 

CTE AS 
(SELECT col1, col2, col3, row_number() over (partition by col3 order by col2) rn 
FROM dataset) 

SELECT A.Col1, A.Col3, A.Col2, B.Col2 as, C.Col2 
FROM cte A 
LEFT JOIN cte B 
on A.Col3 = B.Col3 and A.Rn= 1 and b.rn = 2 
LEFT JOIn cte C 
on A.Col3 = C.Col3 and A.RN =1 and c.RN = 3 

这将导致在一个平坦的输出根据需要,可以接着被放置到单独的表。