带有限制的mysql left join子查询为父选择提供了具有空值的字段

时间:2015-08-22 12:35:02

标签: mysql subquery left-join derived-table

我有一个带有连接和子查询(派生表)的查询。如果我在没有LIMIT 1的情况下运行它,结果将包含vat和带有正确值的id字段。

第一个查询:

SELECT i.id, i.vat, pl.invoice_id as inv_id, pl.product_id as pl_id, pl.quantity as qty, pl.price, pl.currency, p.name, p.manufacturer, p.list_price, p.cost_price, p.wholesale_price, p.cikkszam, p.unit, p.group_name 
FROM soulnsoda_products_log pl 
LEFT JOIN soulnsoda_products p ON pl.product_id=p.id 
LEFT JOIN (select id, vat, parent_id, beneficiary_account from soulnsoda_invoices) as i ON i.parent_id>0 AND pl.invoice_id=i.parent_id AND pl.product_id=i.beneficiary_account 
WHERE pl.action=6 AND p.cikkszam = 'S6511415-BLK' AND (pl.stamp BETWEEN '2015-08-15 00:00:00' AND '2015-08-15 23:59:59') AND pl.warehouse_name='Garage - Árkád'
ORDER BY p.cikkszam

结果将包含带有值的i.id和i.vat字段,但是重复行:

id      vat     inv_id  pl_id   qty     price       name                
93119   27.00   93117   21961   -1.00   1096.85 HUF SUPRA ICON SX BLACK DB
93120   27.00   93117   21961   -1.00   1096.85 HUF SUPRA ICON SX BLACK DB
93119   27.00   93117   21961   -1.00   1096.85 HUF SUPRA ICON SX BLACK DB
93120   27.00   93117   21961   -1.00   1096.85 HUF SUPRA ICON SX BLACK DB  

我必须过滤掉带有重复ID的行。当我使用LIMIT 1时,复制将会消失,但id和vat字段将为NULL。我不知道为什么......

使用LIMIT的第二个查询:

SELECT i.id, i.vat, pl.invoice_id as inv_id, pl.product_id as pl_id, pl.quantity as qty, pl.price, pl.currency, p.name, p.manufacturer, p.list_price, p.cost_price, p.wholesale_price, p.cikkszam, p.unit, p.group_name 
FROM soulnsoda_products_log pl 
LEFT JOIN soulnsoda_products p ON pl.product_id=p.id 
LEFT JOIN (select id, vat, parent_id, beneficiary_account from soulnsoda_invoices LIMIT 1) as i ON i.parent_id>0 AND pl.invoice_id=i.parent_id AND pl.product_id=i.beneficiary_account 
WHERE pl.action=6 AND p.cikkszam = 'S6511415-BLK' AND (pl.stamp BETWEEN '2015-08-15 00:00:00' AND '2015-08-15 23:59:59') AND pl.warehouse_name='Garage - Árkád'
ORDER BY p.cikkszam

结果将是两行,这是好的,但没有id和vat:

id      vat     inv_id  pl_id   qty     price       name                
NULL    NULL    93117   21961   -1.00   1096.85 HUF SUPRA ICON SX BLACK DB
NULL    NULL    93117   21961   -1.00   1096.85 HUF SUPRA ICON SX BLACK DB

我尝试了LIMIT 1,GROUP BY,MIN,MAX等

我知道DISTINCT正在处理我的示例,但这是一个简化的查询,可以向您展示问题本身。

如何在只有两行的情况下实现结果,但在id和vat列中使用某个技术,在LEFT JOIN子查询中使用某些技术?

2 个答案:

答案 0 :(得分:0)

如果您的问题是重复行,请使用select distinct。实际上,最好找到重复的原因,但这可能是你想要的:

SELECT distinct i.id, i.vat, pl.invoice_id as inv_id, pl.product_id as pl_id,
       pl.quantity as qty, pl.price, pl.currency, p.name, p.manufacturer, 
       p.list_price, p.cost_price, p.wholesale_price, p.cikkszam, p.unit, p.group_name 
FROM soulnsoda_products_log pl LEFT JOIN
     soulnsoda_products p
     ON pl.product_id = p.id LEFT JOIN
     soulnsoda_invoices i
     ON i.parent_id > 0 AND pl.invoice_id = i.parent_id AND
        pl.product_id = i.beneficiary_account 
WHERE pl.action = 6 AND
      p.cikkszam = 'S6511415-BLK' AND
      pl.stamp >= '2015-08-15' AND pl.stamp < '2015-08-16' AND    
      pl.warehouse_name = 'Garage - Árkád'
ORDER BY p.cikkszam

一些注意事项:

  • left join上的p正在被where条款转变为内部联接。
  • 子查询不是必需的,实际上只会伤害性能。
  • 此版本简化了日期比较。

答案 1 :(得分:0)

在第一个查询中,子句WHERE ... p.cikkszam = 'S6511415-BLK'将您的第一个LEFT JOIN转换为普通的内部JOIN。

ORDER BY p.cikkszam子句与WHERE ... p.cikkszam = 'S6511415-BLK'结合使用时不执行任何操作:结果集的该列中只有一个值。

您的时间戳间隔结束匹配有点笨拙且差不多正确。试试这个,这将是完美的。

         pl.stamp >= '2015-08-15'
     AND pl.stamp <  '2015-08-15' + INTERVAL 1 DAY

在您的第二个查询中,此子查询子句仅允许将一个随机选择的发票行连接到查询的其余部分:

   select id, vat, parent_id, beneficiary_account from soulnsoda_invoices LIMIT 1

选择&#34;首先&#34;发票表的一行。麻烦的是,没有ORDER BY MySQL和其他RDMS引擎没有坚实的概念&#34;首先&#34;。所以你的第二个问题是对的。

您的查询似乎要求特定产品('S6511415-BLK')在特定日期从某个仓库发货(action=6)每张发票一行。数据中的发票表中有两个匹配的行。在其他一些表中还有两个匹配的行。或者,您的发票表中可能有四个匹配的行。

您尚未向我们描述表格的内容。因此,我们很难帮助您找出重复行的位置。如果您愿意,可以使用SELECT DISTINCT消除发票表中的重复项。

这是我建议的查询。这将为您提供两行结果集。

SELECT i.id, i.vat, 
       pl.invoice_id as inv_id, pl.product_id as pl_id, pl.quantity as qty,
       pl.price, pl.currency,
       p.name, p.manufacturer, p.list_price, p.cost_price,
       p.wholesale_price, p.cikkszam, p.unit, p.group_name 
  FROM soulnsoda_products_log pl 
  JOIN soulnsoda_products p ON pl.product_id=p.id 
  LEFT JOIN (SELECT DISTINCT id, vat,
                             parent_id, beneficiary_account
                        FROM soulnsoda_invoices
            ) as i ON  i.parent_id > 0 
                   AND pl.invoice_id = i.parent_id
                   AND pl.product_id = i.beneficiary_account    
 WHERE pl.action=6
   AND p.cikkszam = 'S6511415-BLK' 
   AND pl.stamp >= '2015-08-15'
   AND pl.stamp <  '2015-08-15' + INTERVAL 1 DAY
   AND pl.warehouse_name='Garage - Árkád'
 ORDER BY p.cikkszam, i.id