[英]How to select first row only in 2nd table of inner join query
我正在使用以下查询从3个不同的表中选择数据。 tbl_invoices和tbl_clients具有唯一记录。 每个tbl_invoices记录都有多个tbl_invoice_entries记录:
$query = 'SELECT T1.*, T2.*, T3.*
FROM tbl_invoices T1
LEFT JOIN tbl_invoice_entries T2
ON T1.number = T2.invoice_number
LEFT JOIN tbl_clients T3
ON T1.client = T3.client_id
WHERE date_format(date, '%Y') = ".$_POST['year']." AND date_format(date, '%c') = ".$_POST['month']." ORDER BY date, number ASC'
$stmt = $conn->prepare($query)
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
当前,这将返回tbl_invoice_entries中的所有记录。 我如何更改查询以仅返回每个tbl_invoices记录的第一个tbl_invoice_entries记录。
表格如下:
tbl_clients
+----+-----------+----------+
| id | firstname | lastname |
+----+-----------+----------+
| 1 | John | Doe |
| 2 | Jane | Doe |
+----+-----------+----------+
tbl_invoices
+----+--------+--------+------------+
| id | number | client | date |
+----+--------+--------+------------+
| 1 | 14 | 1 | 2015-07-14 |
| 1 | 15 | 2 | 2015-07-14 |
+----+--------+--------+------------+
tbl_invoice_entries
+----+----------------+------------+
| id | invoice_number | produkt |
+----+----------------+------------+
| 1 | 14 | Fish |
| 2 | 14 | Bread |
| 3 | 15 | Vegetables |
| 4 | 15 | Fruit |
+----+----------------+------------+
所以我要寻找的结果是:
John Doe 14鱼2015-07-14
Jane Doe 15蔬菜2015-07-14
谢谢你的帮助!
通过不直接通过发票编号链接invoice_entries表,而是通过其第一个条目的ID链接,您可以实现所需的功能:
SELECT firstname,lastname,number,product,date
FROM tbl_invoices T1
LEFT JOIN tbl_invoice_entries T2
ON T2.id =(select min(id) from tbl_invoice_entries
where invoice_number=number)
LEFT JOIN tbl_clients T3
ON T1.client = T3.id
WHERE ...
您需要在第一行告诉RDBMS您打算做什么。 元组中没有自然顺序。 如果您希望给最低ID的元组指定相同的invoice_number ,则将需要另一个查询
SELECT tbl1.* FROM tbl_invoice_entries AS tbl1
JOIN ( SELECT MIN(id) AS id, invoice_number FROM tbl_invoice_entries
GROUP BY invoice_number ) AS tbl2
USING (id);
上面的查询等效于tbl_invoice_entries
但每个发票编号的ID最低。 您可以将其作为VIEW(实际上是两个,因为您不能在VIEW中使用子查询):
CREATE VIEW tbl_invoice_entries_firstnumber AS
SELECT MIN(id) AS id, invoice_number
FROM tbl_invoice_entries
GROUP BY invoice_number;
CREATE VIEW tbl_invoice_entries_first AS
SELECT tbl1.* FROM tbl_invoice_entries AS tbl1
JOIN tbl_invoice_entries_firstnumber
USING (id);
之后,您可以在当前查询中使用tbl_invoice_entries_first
代替tbl_invoice_entries
。
请记住,视图是动态视图,因此它只是更复杂查询的简写形式。 这意味着您当前的查询将变得更加复杂,并且需要更长的时间:
SELECT T1.*, T2.*, T3.*
FROM tbl_invoices AS T1
LEFT JOIN tbl_invoice_entries_first AS T2
ON T1.number = T2.invoice_number
LEFT JOIN tbl_clients AS T3
ON T1.client = T3.id; -- you have no client_id in T3
我在这里摆了一个小提琴。
或者,您可以进一步修改查询,并在T2上添加JOIN条件,以便它仅再次获取最小ID-或您喜欢的任何排序条件:
SELECT T1.*, T2.*, T3.*
FROM tbl_invoices AS T1
LEFT JOIN tbl_invoice_entries AS T2
ON (
-- (( T1.number = T2.invoice_number AND )) --
T2.id = (
SELECT MIN(id) FROM tbl_invoice_entries
WHERE invoice_number = number
))
LEFT JOIN tbl_clients AS T3
ON T1.client = T3.id;
更新 : 对数字的检查已被注释掉(另请参阅@ cars10的解决方案),因为它由内部子查询继承。
最后,您可以在代码中执行此操作,即保存上一个元组的值并根据需要对查询进行排序; 然后丢弃所有不需要的元组。 如果每个发票的条目很少,这可能是值得的:
// pseudo code
if (prev.client == tuple.client)
and
(prev.invoice == tuple.invoice)
continue;
prev = tuple;
-- use tuple.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.