我在Postgresql中遇到了一个"高级"(按照我的标准)查询的问题,我不确定应该如何寻找答案(关键字等)。。。
我有两个表:一个是账单,一个是交易,我想输出的表只包含那些1)比账单最近,2)低于或等于账单3)特定账户或以现金支付的交易。
这个查询可以做到这一点,但我想它可以优化:
((SELECT * FROM transactions
WHERE amount = to_number('$bill_amount','99999999D99')
AND acc_int = 'cash'
AND date > to_date('$bill_date', 'YYYY-MM-DD'))
UNION
(SELECT * FROM transactions
WHERE amount = to_number('$bill_amount','99999999D99')
AND acc_int = 'xxx-xxxxxxx-xx'
AND date > to_date('$bill_date', 'YYYY-MM-DD'))
ORDER BY date DESC)
UNION
((SELECT * FROM transactions
WHERE amount < to_number('$bill_amount','99999999D99')
AND acc_int = 'cash'
AND date > to_date('$bill_date', 'YYYY-MM-DD'))
UNION
(SELECT * FROM transactions
WHERE amount < to_number('$bill_amount','99999999D99')
AND acc_int = 'xxx-xxxxxxx-xx'
AND date > to_date('$bill_date', 'YYYY-MM-DD'))
ORDER BY date DESC)
如果我可以简单地将OR
添加到"acc_int"条件中而不破坏其他条件,则可以合并前两个选择。我认为应该使用括号来完成,但似乎不起作用。
此外,我想对结果进行排序,以便首先所有与账单金额相等的交易,然后按日期计算较低的金额——这就是为什么我将前两个选择与后两个选择相结合,但使用UNION
似乎会打乱排序。
任何见解的THX(欢迎回答或链接到好的资源!)
完整的查询可能如下所示:
SELECT *
FROM transactions
WHERE amount <= to_number('$bill_amount','99999999D99')
AND acc_int IN ('cash', 'xxx-xxxxxxx-xx')
AND date > to_date('$bill_date', 'YYYY-MM-DD')
ORDER BY
(amount <> to_number('$bill_amount','99999999D99'))
, date DESC
FALSE
排序在TRUE
之前,这就是为什么我在ORDER BY
表达式中有<>
运算符。请注意,在原始查询中,
UNION
会删除重复的行。如果表中没有完全的重复项,则结果是相同的(并且UNION ALL
会是更好的选择)。如果你这样做了,添加一个DISTINCT
子句:SELECT DISTINCT * ...
你写道
OR
似乎不适合你。但它应该。这AND acc_int IN ('cash', 'xxx-xxxxxxx-xx')
完全等同于:
AND (acc_int = 'cash' OR acc_int = 'xxx-xxxxxxx-xx')
事实上,查询规划器将第一个表单重写为第二个表单。
可能是这样的:
SELECT * FROM transactions
WHERE amount <= to_number('$bill_amount','99999999D99')
AND acc_int IN ('cash', 'xxx-xxxxxxx-xx')
AND date = to_date('$bill_date', 'YYYY-MM-DD')
ORDER BY date DESC