带有AND/OR/UNION的postgresql查询



我在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

最新更新