我正在尝试查找所有在sales_item_taxes表中都有条目的sale_id,但在sales_items表中没有相应的条目。
mysql> describe phppos_sales_items_taxes;
+------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+-------+
| sale_id | int(10) | NO | PRI | NULL | |
| item_id | int(10) | NO | PRI | NULL | |
| line | int(3) | NO | PRI | 0 | |
| name | varchar(255) | NO | PRI | NULL | |
| percent | decimal(15,3) | NO | PRI | NULL | |
| cumulative | int(1) | NO | | 0 | |
+------------+---------------+------+-----+---------+-------+
6 rows in set (0.01 sec)
mysql> describe phppos_sales_items;
+--------------------+----------------+------+-----+--------------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+----------------+------+-----+--------------+-------+
| sale_id | int(10) | NO | PRI | 0 | |
| item_id | int(10) | NO | PRI | 0 | |
| description | varchar(255) | YES | | NULL | |
| serialnumber | varchar(255) | YES | | NULL | |
| line | int(3) | NO | PRI | 0 | |
| quantity_purchased | decimal(23,10) | NO | | 0.0000000000 | |
| item_cost_price | decimal(23,10) | NO | | NULL | |
| item_unit_price | decimal(23,10) | NO | | NULL | |
| discount_percent | int(11) | NO | | 0 | |
+--------------------+----------------+------+-----+--------------+-------+
9 rows in set (0.00 sec)
mysql>
提议的查询:
SELECT DISTINCT sale_id
FROM phppos_sales_items_taxes
WHERE item_id NOT IN
(SELECT item_id FROM phppos_sales_items WHERE sale_id = phppos_sales_items_taxes.sale_id)
我感到困惑的部分是子查询。查询似乎按预期工作,但我不理解子查询部分。它如何看待每次销售?
例如,如果我有以下数据:
mysql> select * from phppos_sales;
+---------------------+-------------+-------------+---------+-------------------------+---------+--------------------+-----------+-----------+------------+---------+-----------+-----------------------+-------------+---------+
| sale_time | customer_id | employee_id | comment | show_comment_on_receipt | sale_id | payment_type | cc_ref_no | auth_code | deleted_by | deleted | suspended | store_account_payment | location_id | tier_id |
+---------------------+-------------+-------------+---------+-------------------------+---------+--------------------+-----------+-----------+------------+---------+-----------+-----------------------+-------------+---------+
| 2014-08-09 17:53:38 | NULL | 1 | | 0 | 1 | Cash: $12.96<br /> | | | NULL | 0 | 0 | 0 | 1 | NULL |
| 2014-08-09 17:56:59 | NULL | 1 | | 0 | 2 | Cash: $12.96<br /> | | | NULL | 0 | 0 | 0 | 1 | NULL |
+---------------------+-------------+-------------+---------+-------------------------+---------+--------------------+-----------+-----------+------------+---------+-----------+-----------------------+-------------+---------+
mysql> select * from phppos_sales_items;
+---------+---------+-------------+--------------+------+--------------------+-----------------+-----------------+------------------+
| sale_id | item_id | description | serialnumber | line | quantity_purchased | item_cost_price | item_unit_price | discount_percent |
+---------+---------+-------------+--------------+------+--------------------+-----------------+-----------------+------------------+
| 2 | 1 | | | 1 | 1.0000000000 | 10.0000000000 | 12.0000000000 | 0 |
+---------+---------+-------------+--------------+------+--------------------+-----------------+-----------------+------------------+
1 row in set (0.00 sec)
mysql> select * from phppos_sales_items_taxes;
+---------+---------+------+-----------+---------+------------+
| sale_id | item_id | line | name | percent | cumulative |
+---------+---------+------+-----------+---------+------------+
| 1 | 1 | 1 | Sales Tax | 8.000 | 0 |
| 2 | 1 | 1 | Sales Tax | 8.000 | 0 |
+---------+---------+------+-----------+---------+------------+
2 rows in set (0.00 sec)
当我运行下面的查询时,它确实找到了sale_id 1.但子查询如何知道正确过滤。我想我不理解子查询是如何工作的。
mysql> SELECT DISTINCT sale_id
-> FROM phppos_sales_items_taxes
-> WHERE item_id NOT IN
-> (SELECT item_id FROM phppos_sales_items WHERE sale_id = phppos_sales_items_taxes.sale_id)
-> ;
+---------+
| sale_id |
+---------+
| 1 |
+---------+
1 row in set (0.00 sec)
答案 0 :(得分:2)
Duffy356链接到SQL-Joins是好的,但有时看到你自己的数据可能有时更有意义......
首先,你的查询书面显然对于引擎来说非常昂贵。它如何知道要包含的内容是因为它正在执行相关的子查询 - 这意味着对于sales_items_taxes表中的每条记录,它正在对sales_items表运行查询,该表返回所述sale_id的每个可能项。然后它返回主查询并将其与sales_items_taxes表进行比较。如果找不到,则允许将sale_id包含在结果集中。然后它转到sales_items_taxes表中的下一条记录。
(您的查询已重新格式化以提高可读性)
SELECT DISTINCT
sale_id
FROM
phppos_sales_items_taxes
WHERE
item_id NOT IN ( SELECT item_id
FROM phppos_sales_items
WHERE sale_id = phppos_sales_items_taxes.sale_id)
现在,想一想。您有1件特卖,包含100件商品。它运行相关的子查询100次。现在使用1,000个销售ID条目执行此操作,但每个条目都有很多项,很快就会变得昂贵。
更好的选择是利用数据库并进行左连接。索引直接与LEFT JOIN(或内部联接)一起使用,并由引擎优化。此外,请注意我正在为表使用“别名”并限定别名以提高可读性。从您的销售项目税收表开始(您正在寻找额外的条目)是基础。现在,在sales_id和item_id的两个关键组件上左连接此销售项目表。我建议每个表都有一个索引ON(sale_id,item_id)来匹配这里的连接条件。
SELECT DISTINCT
sti.sale_id
FROM
phppos_sales_items_taxes sti
LEFT JOIN phppos_sales_items si
ON sti.sale_id = si.sale_id
AND sti.item_id = si.item_id
WHERE
si.sale_id IS NULL
所以,从这里开始,想一想每张桌子是彼此并排排列的,而你所得到的只是左边的那些(销售物品税)那些没有条目的右侧(sales_items)。
答案 1 :(得分:1)
答案 2 :(得分:0)
你真正想要的是:
SELECT DISTINCT sale_id
FROM phppos_sales_items_taxes
WHERE sale_id NOT IN
(SELECT sale_id FROM phppos_sales_items)
WHERE field NOT IN (SELECT field FROM anothertable WHERE ...)
是一个完美的查询结构。
答案 3 :(得分:0)
您的原始查询:
SELECT DISTINCT sale_id 来自phppos_sales_items_taxes WHERE item_id NOT IN (SELECT item_id FROM phppos_sales_items WHERE sale_id = phppos_sales_items_taxes.sale_id)
在这里,您将从phppos_sales_items表中提取所有item_id,其中sale_id与tax表匹配,并从最终结果中删除这些item_id。
您也可以通过其他方式获得相同的结果,这可能很容易理解。
- 这种形式的查询易于阅读和理解。性能可能不适合大型表。
我也会提出与&#39; bwperrin&#39;相同的解决方案。做了 - 不知道为什么你没有通过运行查询得到任何输出。如果您的标准是在sale_id上过滤 - 这是最佳解决方案。但看起来您正在使用(sale_id,item_id)作为识别销售记录的方法。确保您的表结构有意义。