php - 选择某商品一个月内的最后一笔交易

标签 php mysql

我正在开发一个库存系统。这是我的表格:

药品表:

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,我建议您研究窗口函数。如果最后一个子查询不起作用,请考虑使用左连接而不是嵌套选择。我这样做只是为了向您展示差异。

还有一些提示;

  1. 尽量避免使用非字母字符作为列名称和别名

  2. 使表格和列更具描述性

  3. 使用数据库时坚持使用下划线符号(更简洁)

  4. 避免表中出现冗余。注意到 transacType 有多么冗余吗?为什么不使用两个单独的表进行输入/输出事务?

希望这对您有帮助。祝你好运!

关于php - 选择某商品一个月内的最后一笔交易,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57518849/

相关文章:

php - 使用 Omnipay 在 Paypal Express 中显示账单和运输信息

javascript - 在选择另一个选择字段时创建动态选择字段

mysql - 按小时分组时,分组依据应返回 0。这个怎么做?

mysql - 如何在 SQL 中的 AND 语句后添加条件检查?

php - 如何模拟订阅的逾期状态

php - XmlHttpRequest 状态 = 远程服务器上的 0,本地主机上的状态 200

mysql - sql 删除带有 where、and 或 laravel 的查询

javascript - Maplace.js 谷歌地图不会显示在 Bootstrap 选项卡上

javascript - 如何在上下文中搜索并突出显示字符串的每次出现

schema - 在 MySQL 中提取现有模式,出现未知错误,需要帮助