简体   繁体   中英

Sorting dates differently based on true/false flag

I am trying to sort a date column based on whether the paid flag is true or false. If the paid flag is false (unpaid) I want the oldest to show up first. If the paid flag is true I want the newest to show up first.

Current Query:

SELECT due_date, date_paid, 
    IF(i.date_paid IS NULL, 0, 1) AS paid_flag 
FROM tc_vendorInvoices 
ORDER BY paid_flag, 
        CASE WHEN paid_flag = 0 THEN due_date END ASC, 
        CASE WHEN paid_flag = 0 THEN due_date END DESC 
LIMIT 0, 50

This only sorts the paid flags, and due date is ASC:

due_date   |    date_paid     |  paid_flag
2020-09-28          NULL             0
2020-09-29          NULL             0
2020-10-01          NULL             0
2020-09-14      2020-09-14           1 
2020-09-29      2020-09-29           1
2020-10-05      2020-10-05           1

It needs to sort like this:

due_date   |    date_paid     |  paid_flag
2020-09-28          NULL              0
2020-09-29          NULL              0
2020-10-01          NULL              0
2020-10-05      2020-10-05            1
2020-09-29      2020-09-29            1
2020-09-14      2020-09-14            1

A trick with the boolean flag paid_flag and the function to_seconds() will do it:

order by paid_flag,
         ((not paid_flag) - paid_flag) * to_seconds(due_date)

When paid_flag is 0 , then ((not paid_flag) - paid_flag) returns 1 so the sorting is ascending.
When paid_flag is 1 , then ((not paid_flag) - paid_flag) returns -1 so the sorting is done by -to_seconds(due_date) which is descending.

See the demo .
Results:

> due_date   | date_paid  | paid_flag
> :----------| :--------- | --------:
> 2020-09-28 | null       |         0
> 2020-09-29 | null       |         0
> 2020-10-01 | null       |         0
> 2020-10-05 | 2020-10-05 |         1
> 2020-09-29 | 2020-09-29 |         1
> 2020-09-14 | 2020-09-14 |         1

We can't move the ASC or DESC inside an expression, it's part of the ORDER BY clause. So a construct like this is okay:

ORDER  
   BY fee
    , fi    DESC
    , fo    ASC

We can use expressions to conditionally return a value, and then sort on that expression. The trick is to return a fixed value for the rows we don't want to be sorted.

Something like this:

ORDER BY paid_flag
       , CASE paid_flag WHEN 0 THEN due_date ELSE NULL     END  ASC
       , CASE paid_flag WHEN 0 THEN NULL     ELSE due_date END  DESC 

There are other approaches; this one just happens to closely mimic the approach it looks like the original was attempting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM