SQL: UNION realestate priorities offers - mysql

i'm trying to write a sql query to list all offers from database but first to retrive priorities NOT NULL order by rand then priorities NULL order by id.
I`ve made some kind of this:
(SELECT anunt_lista_id
FROM anunturi__lista
WHERE anunt_lista_is_prioritar IS NOT NULL
ORDER BY RAND())
UNION
(SELECT anunt_lista_id
FROM anunturi__lista
WHERE anunt_lista_is_prioritar IS NULL
ORDER BY anunt_lista_id ASC)
LIMIT 100
but ORDER BY is ignored, no one is applied.
There is another way to this and using another way to do RAND() because as i know this is too slow?

ORDER BY in individual parts of UNION is only useful when you add a LIMIT clause to that specific part, otherwise it is ignored.
From the docs:
To apply ORDER BY or LIMIT to an individual SELECT, place the clause
inside the parentheses that enclose the SELECT:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
However, use of ORDER BY for individual SELECT statements implies
nothing about the order in which the rows appear in the final result
because UNION by default produces an unordered set of rows. Therefore,
the use of ORDER BY in this context is typically in conjunction with
LIMIT, so that it is used to determine the subset of the selected rows
to retrieve for the SELECT, even though it does not necessarily affect
the order of those rows in the final UNION result. If ORDER BY appears
without LIMIT in a SELECT, it is optimized away because it will have
no effect anyway.
If you want the first part of the results to be sorted first, you have to workaround it in some way:
(SELECT anunt_lista_id
FROM anunturi__lista
WHERE anunt_lista_is_prioritar IS NOT NULL)
UNION
(SELECT anunt_lista_id
FROM anunturi__lista
WHERE anunt_lista_is_prioritar IS NULL)
ORDER BY (anunt_lista_is_prioritar IS NULL) ASC,
CASE WHEN anunt_lista_is_prioritar IS NOT NULL THEN
RAND()
ELSE anunt_lista_id END
LIMIT 100
The first clause of the order by: (anunt_lista_is_prioritar IS NULL) ASC is going to give false (0) when it isn't NULL and true (1) when it is NULL. Since it is ordering ASC, 0 will appear first than 1.

You can make dummy columns for order by!
Try this:
SELECT
if(anunt_lista_is_prioritar IS NOT NULL, rand() , 0) as fld_1,
if(anunt_lista_is_prioritar IS NULL,anunt_lista_id , 0) as fld_2,
anunt_lista_id
FROM anunturi__lista
order by fld_1 desc , fld_2 asc
Limit 100

Related

order by with union in SQL is not working

Is it possible to order when the data comes from many select and union it together? Such as
In this statement, the vouchers data is not showing in the same sequence as I saved on the database, I also tried it with "ORDER BY v_payments.payment_id ASC" but won't be worked
( SELECT order_id as id, order_date as date, ... , time FROM orders WHERE client_code = '$searchId' AND order_status = 1 AND order_date BETWEEN '$start_date' AND '$end_date' ORDER BY time)
UNION
( SELECT vouchers.voucher_id as id, vouchers.payment_date as date, v_payments.account_name as name, ac_balance as oldBalance, v_payments.debit as debitAmount, v_payments.description as descriptions,
vouchers.v_no as v_no, vouchers.v_type as v_type, v_payments.credit as creditAmount, time, zero as tax, zero as freightAmount FROM vouchers INNER JOIN v_payments
ON vouchers.voucher_id = v_payments.voucher_id WHERE v_payments.client_code = '$searchId' AND voucher_status = 1 AND vouchers.payment_date BETWEEN '$start_date' AND '$end_date' ORDER BY v_payments.payment_id ASC , time )
UNION
( SELECT return_id as id, return_date as date, ... , time FROM w_return WHERE client_code = '$searchId' AND w_return_status = 1 AND return_date BETWEEN '$start_date' AND '$end_date' ORDER BY time)
Wrap the sub-select queries in the union within a SELECT
SELECT id, name
FROM
(
SELECT id, name FROM fruits
UNION
SELECT id, name FROM vegetables
)
foods
ORDER BY name
If you want the order to only apply to one of the sub-selects, use parentheses as you are doing.
Note that depending on your DB, the syntax may differ here. And if that's the case, you may get better help by specifying what DB server (MySQL, SQL Server, etc.) you are using and any error messages that result.
You need to put the ORDER BY at the end of the statement i.e. you are ordering the final resultset after union-ing the 3 intermediate resultsets
To use an ORDER BY or LIMIT clause to sort or limit the entire UNION result, parenthesize the individual SELECT statements and place the ORDER BY or LIMIT after the last one. See link below:
ORDER BY and LIMIT in Unions
(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;

Query to Display records except Initial Record

For my project, i have a requirement where i have to display all the records in descending order except the first record. I am kind of messed up. Anyways, i have tried the following:
SELECT * FROM ins_nr nl WHERE nl.nl_status = '2' ORDER BY nl.nl_id DESC
Here, i have a table called ins_nr which will display all the records with status 2 and the id which is the primary key(unique). It is displaying in desc order perfectly.
I dont want the first record from the top alone. What should i do? How to modify the above query..?
Use OFFSET. Then you can skip 1 records and select the remaining ones until the end.
Example:
SELECT * FROM ins_nr nl WHERE nl.nl_status = '2'
ORDER BY nl.nl_id DESC LIMIT 99999999999 OFFSET 1;
OR ( You could also use a shorter syntax to achieve the same result: )
$sql = "SELECT * FROM table_name LIMIT 1, 999999999";
You can generate dynamic rownum and filter on it to omit the first row, e.g.:
SELECT *
FROM (
SELECT nl.*, #r := #r + 1 AS `rn`
FROM ins_nr nl, (SELECT #r := 0)
WHERE nl.nl_status = '2'
ORDER BY nl.nl_id DESC
) a
WHERE a.rn > 1;
Another way is to get the max id from subquery and put it in a where clausole
You are looking for the offset clause. This looks like:
SELECT *
FROM ins_nr nl
WHERE nl.nl_status = '2'
ORDER BY nl.nl_id DESC
LIMIT 999999999 OFFET 1;
Unfortunately, LIMIT is required. For this situation, it is traditional to just put in a very large number.
Also, if nl_status is numeric, then use nl.nl_status = 2. Don't compare strings to numbers.

Order an array with null values last [duplicate]

Currently I am doing a very basic OrderBy in my statement.
SELECT * FROM tablename WHERE visible=1 ORDER BY position ASC, id DESC
The problem with this is that NULL entries for 'position' are treated as 0. Therefore all entries with position as NULL appear before those with 1,2,3,4. eg:
NULL, NULL, NULL, 1, 2, 3, 4
Is there a way to achieve the following ordering:
1, 2, 3, 4, NULL, NULL, NULL.
MySQL has an undocumented syntax to sort nulls last. Place a minus sign (-) before the column name and switch the ASC to DESC:
SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC, id DESC
It is essentially the inverse of position DESC placing the NULL values last but otherwise the same as position ASC.
A good reference is here http://troels.arvin.dk/db/rdbms#select-order_by
I found this to be a good solution for the most part:
SELECT * FROM table ORDER BY ISNULL(field), field ASC;
NULL LAST
SELECT * FROM table_name ORDER BY id IS NULL, id ASC
Something like
SELECT * FROM tablename where visible=1 ORDER BY COALESCE(position, 999999999) ASC, id DESC
Replace 999999999 with what ever the max value for the field is
That's simple. You just need to order twice:
first step, order NULLs
second step, order your field.
SELECT * FROM table_name
ORDER BY ISNULL(field_name), field_name;
It works with any types, including JSON.
You can swap out instances of NULL with a different value to sort them first (like 0 or -1) or last (a large number or a letter)...
SELECT field1, IF(field2 IS NULL, 9999, field2) as ordered_field2
FROM tablename
WHERE visible = 1
ORDER BY ordered_field2 ASC, id DESC
Try using this query:
SELECT * FROM tablename
WHERE visible=1
ORDER BY
CASE WHEN position IS NULL THEN 1 ELSE 0 END ASC,id DESC
This works well for me as well.
ORDER BY ISNULL(field), field = 0 ASC;
Returns
1
2
3
0
0
null
null
You can coalesce your NULLs in the ORDER BY statement:
select * from tablename
where <conditions>
order by
coalesce(position, 0) ASC,
id DESC
If you want the NULLs to sort on the bottom, try coalesce(position, 100000). (Make the second number bigger than all of the other position's in the db.)
For a DATE column you can use:
NULLS last:
ORDER BY IFNULL(`myDate`, '9999-12-31') ASC
Blanks last:
ORDER BY IF(`myDate` = '', '9999-12-31', `myDate`) ASC
SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC
To achieve following result :
1, 2, 3, 4, NULL, NULL, NULL.
USE syntax, place -(minus sign) before field name and use inverse order_type(Like: If you want order by ASC order then use DESC or if you want DESC order then use ASC)
SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC
This is working fine:
SELECT * FROM tablename ORDER BY position = 0, position ASC;
position
1
2
3
0
0
Why don't you order by NULLS LAST?
SELECT *
FROM tablename
WHERE visible = 1
ORDER BY position ASC NULLS LAST, id DESC

MySQL Sorting using order by not working using unio

I'm using an union statement in mysql but i've some problems sorting the results. The ORDER statement doesn't works at all, the results comes out always sorted by the id field.
Here an example query:
SELECT a.* FROM ( ( select * from ticket_ticket AS t1 WHERE ticket_active=1 ORDER BY t1.ticket_date_last_modified DESC )
UNION ( select * from ticket_ticket AS t2 WHERE ticket_active=0 ORDER BY t2.ticket_date_last_modified DESC, t2.ticket_status_id DESC ) )
AS a LIMIT 0,20;
I want to order the results of the first SELECT by last_modified time, and the second SELECT by time and status. But the ORDER statement get just skipped. The results always come out ordered by the ticket_id ( the PRIMARY KEY ).
What's wrong in this query ?
Thanks!
Ok, i've fixed it writing the query this way:
SELECT a.*
FROM
(SELECT *
FROM ticket_ticket
WHERE ticket_active=1
ORDER BY ticket_date_last_modified DESC) AS a
UNION ALL
SELECT b.*
FROM
(SELECT *
FROM ticket_ticket
WHERE ticket_active=0
ORDER BY ticket_date_last_modified DESC, ticket_status_id DESC) AS b LIMIT 0,
20;
You are using a UNION query that will return distinct values, and the order of the returned rows is not guaranteed.
But you don't need an union query for this:
select *
from ticket_ticket AS t1
ORDER BY
ticket_active!=1,
ticket_date_last_modified DESC,
ticket_status_id DESC
LIMIT 0,20;

MySQL Orderby a number, Nulls last

Currently I am doing a very basic OrderBy in my statement.
SELECT * FROM tablename WHERE visible=1 ORDER BY position ASC, id DESC
The problem with this is that NULL entries for 'position' are treated as 0. Therefore all entries with position as NULL appear before those with 1,2,3,4. eg:
NULL, NULL, NULL, 1, 2, 3, 4
Is there a way to achieve the following ordering:
1, 2, 3, 4, NULL, NULL, NULL.
MySQL has an undocumented syntax to sort nulls last. Place a minus sign (-) before the column name and switch the ASC to DESC:
SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC, id DESC
It is essentially the inverse of position DESC placing the NULL values last but otherwise the same as position ASC.
A good reference is here http://troels.arvin.dk/db/rdbms#select-order_by
I found this to be a good solution for the most part:
SELECT * FROM table ORDER BY ISNULL(field), field ASC;
NULL LAST
SELECT * FROM table_name ORDER BY id IS NULL, id ASC
Something like
SELECT * FROM tablename where visible=1 ORDER BY COALESCE(position, 999999999) ASC, id DESC
Replace 999999999 with what ever the max value for the field is
That's simple. You just need to order twice:
first step, order NULLs
second step, order your field.
SELECT * FROM table_name
ORDER BY ISNULL(field_name), field_name;
It works with any types, including JSON.
You can swap out instances of NULL with a different value to sort them first (like 0 or -1) or last (a large number or a letter)...
SELECT field1, IF(field2 IS NULL, 9999, field2) as ordered_field2
FROM tablename
WHERE visible = 1
ORDER BY ordered_field2 ASC, id DESC
Try using this query:
SELECT * FROM tablename
WHERE visible=1
ORDER BY
CASE WHEN position IS NULL THEN 1 ELSE 0 END ASC,id DESC
This works well for me as well.
ORDER BY ISNULL(field), field = 0 ASC;
Returns
1
2
3
0
0
null
null
You can coalesce your NULLs in the ORDER BY statement:
select * from tablename
where <conditions>
order by
coalesce(position, 0) ASC,
id DESC
If you want the NULLs to sort on the bottom, try coalesce(position, 100000). (Make the second number bigger than all of the other position's in the db.)
For a DATE column you can use:
NULLS last:
ORDER BY IFNULL(`myDate`, '9999-12-31') ASC
Blanks last:
ORDER BY IF(`myDate` = '', '9999-12-31', `myDate`) ASC
SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC
To achieve following result :
1, 2, 3, 4, NULL, NULL, NULL.
USE syntax, place -(minus sign) before field name and use inverse order_type(Like: If you want order by ASC order then use DESC or if you want DESC order then use ASC)
SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC
This is working fine:
SELECT * FROM tablename ORDER BY position = 0, position ASC;
position
1
2
3
0
0
Why don't you order by NULLS LAST?
SELECT *
FROM tablename
WHERE visible = 1
ORDER BY position ASC NULLS LAST, id DESC