加入设计不佳的SQL表?

时间:2013-06-28 22:55:16

标签: sql-server tsql

我已经尝试在没有foriegn键的情况下搜索有关连接表的信息,但似乎答案始终是创建外键。我无法修改有问题的表来执行此操作,并且必须报告已在生产中的数据。以下是所涉及的表中数据的一部分,以便举例说明该问题。

Table A
Journal    Account    Debit    Credit    Sequence
--------------------------------------------------
87041      150-00     100.00   0.00      16384
87041      150-10     0.00     100.00    32768
87041      150-00     50.0     0.0       49152
87041      210-90     0.0      50.0      65536

然后,跟踪其他信息位的第二个表大致相同,但缺少将订单项正确绑定在一起的序号。它有自己的序列号不相关。

Table B
Journal    Account    Label    Artist    Sequence
--------------------------------------------------
87041      150-00     Label02  Artist12  1
87041      150-10     Label09  Artist03  2
87041      150-00     Label04  Artist01  3
87041      210-90     Label01  Artist05  4

目前,我能想到的最好的方法是加入期刊和账户,但重复记录。我已经通过在序列号上使用分组和max()来接近,但结果是,对于具有非常多行的日志条目,并非所有重复项都被删除,并且第二个表中的第一个匹配始终显示为具有相同帐户的行。

Closest - but bad - result
Journal    Account    Debit    Credit    Sequence    Label    Artist
----------------------------------------------------------------------
87041      150-00     100.00   0.00      16384       Label02  Artist12
87041      150-10     0.00     100.00    32768       Label09  Artist03
87041      150-00     50.0     0.0       49152       Label02  Artist12  <-- wrong 
87041      210-90     0.0      50.0      65536       Label01  Artist05

如何连接表格,以便排除重复项,以便显示正确的标签和艺术家?有点像我必须生成一个查询,它知道当表A中的49152记录找到匹配时,已经使用了表B中的一条记录。

编辑:

@Justin Crabtree A.Sequence将是订单项的输入顺序。因此,用户可以先输入示例中的最后一行,然后输入第一行,然后输入第三行,最后输入第二行。

@Edper Microsoft SQL Server ......嗯,今天早上我无法远程进入客户端的机器......否则我会提供该版本。

@Abe Miessler是的,你是对的。

一旦我回到服务器,我会尝试你的建议@pkuderov

4 个答案:

答案 0 :(得分:4)

尝试this

;WITH a AS
(
    SELECT Journal,
           Account,
           Debit,
           Credit,
           Sequence,
           Id = ROW_NUMBER() OVER(PARTITION BY Journal ORDER BY Sequence)
    FROM dbo.tablea
)
, b AS
(
    SELECT Journal,
           Account,
           Label,
           Artist,
           Id = ROW_NUMBER() OVER(PARTITION BY Journal ORDER BY Sequence)
    FROM dbo.tableb
)

SELECT a.Journal,
       a.Account,
       a.Debit,
       a.Credit,
       a.Sequence,
       b.Label,
       b.Artist
FROM a
JOIN b ON b.Journal = a.Journal
      AND b.Account = a.Account
      AND b.Id = a.Id

答案 1 :(得分:3)

嗨,这只是一个想法:

select
    a.Journal, a.Account, a.Debit, a.Credit, a.Sequence, b.Label, b.Artist
from (
    select
        *, 
        row_number() over(partition by Journal, Account order by Sequence) as idInGroup
    from a
) as a
join (
    select
        *, 
        row_number() over(partition by Journal, Account order by Sequence) as idInGroup
    from b
) as b on
    a.Journal = b.Journal
    and a.Account = b.Account
    and a.idInGroup = b.idInGroup

这里我假设订单以顺序顺序出现(在两个表中),这是连接表的基本提示。

答案 2 :(得分:0)

如果您按照自己的序列号排序了2个表格行,那么这些行会以相同的顺序排列吗?

如果是这样,这是SQL服务器的可能解决方案: 您可以使用ROW_NUMBER列为每个表创建2个CTE,这样,两个表都将具有可用于连接的匹配行号列。如果您需要一个例子,请告诉我。

答案 3 :(得分:0)

如果我正确地阅读了您的要求并且您想要表A中的所有行,但只需要表B中的第一个匹配行,那么您最好的选择是使用TOP(1)进行外部应用。这看起来像这样:

select *
from TableA
OUTER APPLY
 (select TOP(1) Journal, Account, Label, Artist, Sequence
  FROM TableB
  WHERE Journal = TableA.Journal AND Account = TableA.Account
  ORDER BY Sequence) as B

(绝对是伪代码,但应该稍微接近。)

如果归结为它,您可以使用ROW_NUMBER(),按日记帐和帐户进行分区,然后匹配每个结果集的Row_Number值。您将为TableA生成一个子查询/ CTE,为TableB生成另一个CTE - 每个都具有RowNumber值,该值基本上是新的序列整数。 TableA中的第一行将与TableB中的第一行匹配,TableA中的第二行将与TableB中的第二行匹配,等等。当然,如果在&#中有更多的Journal / Account行,则会遇到一些问题34; A&#34;比在&#34; B&#34;。

更好的问题可能是 - &#34;如果代码无法使用任何数据列将它们绑定在一起,那么您的代码如何确定TableA和TableB之间的所有匹配?&#34;