我正在开发一个库存系统。这是我的表格:
药品表:
medID| medDescription | medBeginningQty |
+++++++++++++++++++++++++++++++++++++++++
1 | Amplodipine |5000 |
2 | Losartan 5mg |5000 |
3 | Amoxicillin |5000 |
4 | Paracetamol |5000 |
5 | Ascorbic Acid |5000 |
6 | Co-amoxiclav |5000 |
7 | Alcohol |5000 |
8 | Losartan 10mg |5000 |
medicinetransac 表:
medTransacID|medID|transacType|transacQuantity|transacDate|transacCurrentBal
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 | 1 | NewItem | 5000 | 2018-10-01| 5000
2 | 2 | NewItem | 5000 | 2018-10-01| 5000
3 | 3 | NewItem | 5000 | 2018-10-01| 5000
4 | 4 | NewItem | 5000 | 2018-10-01| 5000
5 | 5 | NewItem | 5000 | 2018-10-01| 5000
6 | 6 | NewItem | 5000 | 2018-10-01| 5000
7 | 7 | NewItem | 5000 | 2018-10-01| 5000
8 | 8 | NewItem | 5000 | 2018-10-01| 5000
9 | 1 | issuance | 100 | 2019-07-01| 4900
10 | 2 | issuance | 100 | 2019-07-01| 4900
11 | 3 | issuance | 100 | 2019-07-01| 4900
12 | 1 | issuance | 200 | 2019-07-15| 4700
13 | 2 | issuance | 200 | 2019-07-15| 4700
14 | 3 | issuance | 200 | 2019-07-15| 4700
15 | 2 | issuance | 100 | 2019-08-02| 4600
16 | 5 | issuance | 100 | 2019-08-02| 4900
17 | 3 | issuance | 200 | 2019-08-10| 4500
18 | 5 | issuance | 200 | 2019-08-10| 4800
19 | 6 | issuance | 200 | 2019-08-10| 4800
我想生成一份月度报告,其中我可以获取该月某个项目的最后一次交易,以及该项目在该月之前的最后一次交易,以用作给定月份的期初余额。
此外,如果给定月份没有交易,但数量仍然大于零,那么也可以显示它。这是我的示例代码,无法正常工作Select * from Medicine m left join Medicinetransac mt on m.medID = mt.medID where Month(mt.transacDate) = '$month'
。
这是我希望的输出 $month = "08"
:
medTransacID|medID|medDescription|transacType|BeginningBalanc|transacDate(beginning)|transacDate(last)|transacQuantity
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 | 1 |Amplodipine | issuance | 4700 | 2019-07-15 | ---------- | -
1 | 2 |Losartan 5mg | issuance | 4900 | 2019-07-15 | 2019-08-02 | 100
1 | 3 |Amoxicillin | issuance | 4700 | 2019-07-15 | 2019-08-10 | 200
1 | 4 |Paracetamol | NewItem | 5000 | 2018-10-01 | ---------- | -
1 | 5 |Ascorbic Acid | issuance | 5000 | 2018-10-01 | 2019-08-10 | 200
1 | 6 |Co-Amoxiclav | issuance | 5000 | 2018-10-01 | 2019-08-10 | 200
1 | 7 |Alcohol | NewItem | 5000 | 2018-10-01 | - | -
1 | 8 |Losartan 10mg | NewItem | 5000 | 2018-10-01 | - | -
即使在给定月份内没有交易,medID = 4, 7, 8
的项目也会被捕获,因为数量仍然 > 0。
谢谢!我希望你能理解我如何写我的问题!顺便说一句,我使用 PHP,我不希望一切都通过查询来完成。
最佳答案
尽管您处理表结构的方式似乎有些无效,但我会尝试解决您的担忧,忽略它。
假设您的 PHP 变量包含:
$target_month = '08';
$target_year = date("Y");
我们想要收集年份,因为我们不希望 sql 假设 2019 年 8 月与 2018 年 8 月相同并将它们混合。
调整到您当前的结构,我首先会获取每个项目本月最后交易的子查询。我们使用 GROUP BY 语句和 MAX() 聚合函数的组合来完成此操作。
SELECT medID, MAX(medTransacID) AS lastTransacID
FROM medicinetransac
WHERE MONTH(transacDate) = {$target_month} AND YEAR(transacDate) = {$target_year}
GROUP BY medId
请注意,我们没有获得最后日期(因为每个日期可以有多个交易),因此我们获得的是最高的交易 ID。只要确保它是自动递增的即可。
现在,为了获取上个月的数据,有一些假设。我们需要上个月的数据还是本月之前的最后一笔交易?这是一个巨大的差异,因为如果我们上个月没有交易怎么办?如果上次购买商品是 5 个月前怎么办?我们用那个吗?或者我们显示空白?对于此示例,我假设您想要本月之前的最后一笔交易,无论是上个月还是 3 个月前。
SELECT medId, transacDate, transacCurrentBal
FROM medicinetransac a
WHERE medTransacID = (
SELECT MAX(medTransacID) FROM medicinetransac b
WHERE MONTH(transacDate) < {$target_month}
AND YEAR(transacDate) <= {$target_year}
AND b.medId = a.medId
LIMIT 1
)
因此,在该查询中,我们提取本月之前任何日期中找到的最大交易 ID。请注意我如何使用 < 和 <= 表示日期。
我们现在可以像这样构建这个大查询:
SELECT
med.medID,
med.medDescription,
tmd.transacType,
topmt.transacCurrentBal AS beginningBalance,
topmt.transacDate AS begginingBalanceDate,
tmd.transacDate AS lastTransactionDate,
tmd.transacQuantity AS lastTransactionQuantity
FROM medicine med
LEFT JOIN (
SELECT medID, MAX(medTransacID) AS lastTransacID
FROM medicinetransac
WHERE MONTH(transacDate) = {$target_month} AND YEAR(transacDate) = {$target_year}
GROUP BY medId
) table_of_last_transaction_ids tolti ON med.medID = tolti.medID
LEFT JOIN medicinetransac target_month_data tmd ON tmd.medTransacID = tolti.medTransacId
LEFT JOIN (
SELECT medId, transacDate, transacCurrentBal
FROM medicinetransac a
WHERE medTransacID = (
SELECT MAX(medTransacID) FROM medicinetransac b
WHERE MONTH(transacDate) < {$target_month}
AND YEAR(transacDate) <= {$target_year}
AND b.medId = a.medId
LIMIT 1
)
) table_of_previous_months_transaction topmt ON topmt.medId = med.medId
但是,对此有一些注意事项。子查询通常很慢,如果您使用的是更新版本的 mysql,我建议您研究窗口函数。如果最后一个子查询不起作用,请考虑使用左连接而不是嵌套选择。我这样做只是为了向您展示差异。
还有一些提示;
尽量避免使用非字母字符作为列名称和别名
使表格和列更具描述性
使用数据库时坚持使用下划线符号(更简洁)
避免表中出现冗余。注意到 transacType 有多么冗余吗?为什么不使用两个单独的表进行输入/输出事务?
希望这对您有帮助。祝你好运!
关于php - 选择某商品一个月内的最后一笔交易,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57518849/