简体   繁体   English

SQL联接到仅一行

[英]SQL JOIN to Only One Row

I have 2 sale data tables that have no common keys, just sale date and customer name. 我有2个销售数据表,没有公用密钥,只有销售日期和客户名称。 I want to join them so that for each row from table A there will be at most 1 match from table B, or 0 if none is found. 我想加入它们,以便表A中的每一行最多有表B中的1个匹配项,如果找不到则为0。 The problem is if the same customer shows up twice on the same date. 问题是同一客户在同一日期出现两次。 So if I have data like these 所以如果我有这些数据

Table A                             Table B

Customer | Date       | Receipt     Customer | Date       | Invoice
===============================     ===============================
John     | 2018-01-01 | A           John     | 2018-01-01 | C
John     | 2018-01-01 | B           John     | 2018-01-01 | D

How do I get this 我怎么得到这个

Result

Customer | Date       | Receipt | Invoice
=========================================
John     | 2018-01-01 | A       | C
John     | 2018-01-01 | B       | D

It does not matter whether receipt A is matched with Invoice C or D, as long as each is paired once. 只要收据A匹配一次,收据A与发票C或D是否匹配都没有关系。 Currently my query joins all of them, AC, AD, BC, BD 目前,我的查询加入了AC,AD,BC,BD

Edit: to clarify, I can't have duplicates from either table. 编辑:澄清一下,我不能从任何一个表重复。 One invoice and receipt can only appear once. 一张发票和收据只能出现一次。 So either one of these results are acceptable: 因此,这些结果之一是可以接受的:

  • AC and BD AC和BD
  • AD and BC 公元前

This is a pain, because you need to enumerate the two tables and then either join or aggregate. 这很痛苦,因为您需要枚举两个表,然后进行join或聚合。 Here is one way: 这是一种方法:

select customer, date, max(receipt) as receipt, max(invoice) as invoice
from ((select a.customer, a.date, a.receipt,
              (@rnr := if(@cd = concat_ws(';', customer, date), @rnr + 1,
                          if(@cd := concat_ws(';', customer, date), 1, 1)
                         )
              ) as seqnum
       from a cross join
            (select @rnr := 0, @cd := '') params
       order by a.customer, a.date
      ) union all
      (select b.customer, b.date, b.invoice,
              (@rni := if(@cd = concat_ws(';', customer, date), @rni + 1,
                          if(@cd := concat_ws(';', customer, date), 1, 1)
                         )
              ) as seqnum
       from b cross join
            (select @rni := 0, @cd := '') params
       order by a.customer, a.date
      )
     ) cd
group by customer, date, seqnum;

Why not just do a distinct after you've joined your two tables since you only want distinct records? 由于只希望使用不同的记录,为什么在加入两个表之后不只是进行不同的记录呢?

SELECT DISTINCT a.Customer,
a.Date, 
a.Receipt, 
b.Invoice 
FROM Table_A a

JOIN Table_B b
ON a.Customer = b.Customer
AND a.Date = b.Date

I'm going to give an answer you're probably not going to like: this shouldn't be done in SQL. 我将给出一个您可能不会喜欢的答案:这不应该在SQL中完成。 This is a presentation/display issue. 这是一个演示/显示问题。

Do this sort of work in the layer that's displaying the data to the user, not the SQL back end. 在向用户显示数据而不是SQL后端的层中执行此类工作。 Are they looking it up in a web page? 他们在网页上查找吗? Then have the web page get the raw data and format it as needed - have it put the contents of each day's Receipts or each day's Invoices in separate divs. 然后让网页获取原始数据并根据需要对其进行格式化-将每天的收据或每天的发票的内容放在单独的div中。 Is SQL sending out an email with this data? SQL是否使用此数据发送电子邮件? Then don't have it generate a plain-text email - have it generate HTML and put the data into table cells (so you don't have to coordinate rows between two sets of data with possibly differing amounts of data.) 然后,不要让它生成纯文本电子邮件-让它生成HTML并将数据放入表格单元格中(这样,您就不必在数据量可能不同的两组数据之间协调行)。

You really don't want to be playing the game of trying to make SQL output look pretty from within SQL. 您确实不想玩试图使SQL输出在SQL内部看起来很漂亮的游戏。 Because, honestly, the code in the answer you've accepted may work correctly, but I'd hate to be trying to maintain it over the years... 因为,说实话,你已经接受答案的代码可以正常工作 ,但我讨厌试图维护它多年来...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM