UNION query ordered separately by its components
I'm using Postgres 9.6 and I have a query that shows the top 100 rows that contain a specific string, "xyz" in this example. It looks roughly like the following:
SELECT name FROM data WHERE name ILIKE '%xyz%' ORDER BY other_column LIMIT 100;
What I actually want to achieve is to put the rows that match at the beginning of the name column in front. So still 100 rows in total, but first filled from results that match name ILIKE 'xyz%
, and then with results from ILIKE '%xyz%'
.
I tried to achieve this with UNION queries roughly like the following
SELECT name FROM data WHERE name ILIKE 'xyz%'
UNION
SELECT name FROM data WHERE name ILIKE '%xyz%'
ORDER BY other_column
LIMIT 100;
This obviously doesn't work because it's sorted by other_column
. My original idea was to add a column to each query to use for sorting
SELECT 1 as sort_order, name FROM data WHERE name ILIKE 'xyz%'
UNION
SELECT 2 as sort_order, name FROM data WHERE name ILIKE '%xyz%'
ORDER BY sort_order, other_column
LIMIT 100;
But that kills the duplicate removal of UNION
and instead behaves like UNION ALL
because I'm making originally identical rows different with the addition of the sort_order column.
I could of course do the duplicate removal in a later step outside the database, but that isn't a terribly appealing solution to me. Is there any way to order the individual parts of a UNION query separately, and achieve the results I described?
sql postgresql union
add a comment |
I'm using Postgres 9.6 and I have a query that shows the top 100 rows that contain a specific string, "xyz" in this example. It looks roughly like the following:
SELECT name FROM data WHERE name ILIKE '%xyz%' ORDER BY other_column LIMIT 100;
What I actually want to achieve is to put the rows that match at the beginning of the name column in front. So still 100 rows in total, but first filled from results that match name ILIKE 'xyz%
, and then with results from ILIKE '%xyz%'
.
I tried to achieve this with UNION queries roughly like the following
SELECT name FROM data WHERE name ILIKE 'xyz%'
UNION
SELECT name FROM data WHERE name ILIKE '%xyz%'
ORDER BY other_column
LIMIT 100;
This obviously doesn't work because it's sorted by other_column
. My original idea was to add a column to each query to use for sorting
SELECT 1 as sort_order, name FROM data WHERE name ILIKE 'xyz%'
UNION
SELECT 2 as sort_order, name FROM data WHERE name ILIKE '%xyz%'
ORDER BY sort_order, other_column
LIMIT 100;
But that kills the duplicate removal of UNION
and instead behaves like UNION ALL
because I'm making originally identical rows different with the addition of the sort_order column.
I could of course do the duplicate removal in a later step outside the database, but that isn't a terribly appealing solution to me. Is there any way to order the individual parts of a UNION query separately, and achieve the results I described?
sql postgresql union
add a comment |
I'm using Postgres 9.6 and I have a query that shows the top 100 rows that contain a specific string, "xyz" in this example. It looks roughly like the following:
SELECT name FROM data WHERE name ILIKE '%xyz%' ORDER BY other_column LIMIT 100;
What I actually want to achieve is to put the rows that match at the beginning of the name column in front. So still 100 rows in total, but first filled from results that match name ILIKE 'xyz%
, and then with results from ILIKE '%xyz%'
.
I tried to achieve this with UNION queries roughly like the following
SELECT name FROM data WHERE name ILIKE 'xyz%'
UNION
SELECT name FROM data WHERE name ILIKE '%xyz%'
ORDER BY other_column
LIMIT 100;
This obviously doesn't work because it's sorted by other_column
. My original idea was to add a column to each query to use for sorting
SELECT 1 as sort_order, name FROM data WHERE name ILIKE 'xyz%'
UNION
SELECT 2 as sort_order, name FROM data WHERE name ILIKE '%xyz%'
ORDER BY sort_order, other_column
LIMIT 100;
But that kills the duplicate removal of UNION
and instead behaves like UNION ALL
because I'm making originally identical rows different with the addition of the sort_order column.
I could of course do the duplicate removal in a later step outside the database, but that isn't a terribly appealing solution to me. Is there any way to order the individual parts of a UNION query separately, and achieve the results I described?
sql postgresql union
I'm using Postgres 9.6 and I have a query that shows the top 100 rows that contain a specific string, "xyz" in this example. It looks roughly like the following:
SELECT name FROM data WHERE name ILIKE '%xyz%' ORDER BY other_column LIMIT 100;
What I actually want to achieve is to put the rows that match at the beginning of the name column in front. So still 100 rows in total, but first filled from results that match name ILIKE 'xyz%
, and then with results from ILIKE '%xyz%'
.
I tried to achieve this with UNION queries roughly like the following
SELECT name FROM data WHERE name ILIKE 'xyz%'
UNION
SELECT name FROM data WHERE name ILIKE '%xyz%'
ORDER BY other_column
LIMIT 100;
This obviously doesn't work because it's sorted by other_column
. My original idea was to add a column to each query to use for sorting
SELECT 1 as sort_order, name FROM data WHERE name ILIKE 'xyz%'
UNION
SELECT 2 as sort_order, name FROM data WHERE name ILIKE '%xyz%'
ORDER BY sort_order, other_column
LIMIT 100;
But that kills the duplicate removal of UNION
and instead behaves like UNION ALL
because I'm making originally identical rows different with the addition of the sort_order column.
I could of course do the duplicate removal in a later step outside the database, but that isn't a terribly appealing solution to me. Is there any way to order the individual parts of a UNION query separately, and achieve the results I described?
sql postgresql union
sql postgresql union
asked Nov 21 '18 at 17:23
Mad ScientistMad Scientist
11.3k96288
11.3k96288
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Use the function position(substring in string)
instead of UNION, example:
WITH data(name, other_column) AS (
VALUES
('abc xyz', 1),
('xyz abc', 2),
('a xyz b', 3),
('xyz abc', 4)
)
SELECT name, other_column
FROM data
WHERE name ILIKE '%xyz%'
ORDER BY position('xyz' in name), other_column
LIMIT 100;
name | other_column
---------+--------------
xyz abc | 2
xyz abc | 4
a xyz b | 3
abc xyz | 1
(4 rows)
or:
SELECT name, other_column
FROM data
WHERE name ILIKE '%xyz%'
ORDER BY position('xyz' in name) > 1, other_column
LIMIT 100;
name | other_column
---------+--------------
xyz abc | 2
xyz abc | 4
abc xyz | 1
a xyz b | 3
(4 rows)
Sozxyz
will be beforeaaxyz
– forpas
Nov 21 '18 at 18:01
@forpas - Use the second variant, if it matters.
– klin
Nov 21 '18 at 18:03
add a comment |
By using other_column
:
SELECT t.name FROM (
SELECT name, CONCAT(' ', name) AS other_column FROM data WHERE (name ILIKE 'xyz%')
UNION
SELECT name, name AS other_column FROM data WHERE (name ILIKE '%xyz%') AND (name NOT ILIKE 'xyz%')
) AS t
ORDER BY t.other_column
LIMIT 100;
What this does is append a prefix of blank space (ASCII 32) to name
in the first list and creates other_column
.
In the second list other_column
is the same as the name
.
Finally sorts by other_column
.
as far as I understand, the sort order is unpredictable in case of UNION without an ORDER BY clause due to the duplicate removal.
– Mad Scientist
Nov 21 '18 at 17:43
so this will make me think about it. I will delete after you read.
– forpas
Nov 21 '18 at 17:46
@MadScientist check this.
– forpas
Nov 21 '18 at 18:12
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53417540%2funion-query-ordered-separately-by-its-components%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Use the function position(substring in string)
instead of UNION, example:
WITH data(name, other_column) AS (
VALUES
('abc xyz', 1),
('xyz abc', 2),
('a xyz b', 3),
('xyz abc', 4)
)
SELECT name, other_column
FROM data
WHERE name ILIKE '%xyz%'
ORDER BY position('xyz' in name), other_column
LIMIT 100;
name | other_column
---------+--------------
xyz abc | 2
xyz abc | 4
a xyz b | 3
abc xyz | 1
(4 rows)
or:
SELECT name, other_column
FROM data
WHERE name ILIKE '%xyz%'
ORDER BY position('xyz' in name) > 1, other_column
LIMIT 100;
name | other_column
---------+--------------
xyz abc | 2
xyz abc | 4
abc xyz | 1
a xyz b | 3
(4 rows)
Sozxyz
will be beforeaaxyz
– forpas
Nov 21 '18 at 18:01
@forpas - Use the second variant, if it matters.
– klin
Nov 21 '18 at 18:03
add a comment |
Use the function position(substring in string)
instead of UNION, example:
WITH data(name, other_column) AS (
VALUES
('abc xyz', 1),
('xyz abc', 2),
('a xyz b', 3),
('xyz abc', 4)
)
SELECT name, other_column
FROM data
WHERE name ILIKE '%xyz%'
ORDER BY position('xyz' in name), other_column
LIMIT 100;
name | other_column
---------+--------------
xyz abc | 2
xyz abc | 4
a xyz b | 3
abc xyz | 1
(4 rows)
or:
SELECT name, other_column
FROM data
WHERE name ILIKE '%xyz%'
ORDER BY position('xyz' in name) > 1, other_column
LIMIT 100;
name | other_column
---------+--------------
xyz abc | 2
xyz abc | 4
abc xyz | 1
a xyz b | 3
(4 rows)
Sozxyz
will be beforeaaxyz
– forpas
Nov 21 '18 at 18:01
@forpas - Use the second variant, if it matters.
– klin
Nov 21 '18 at 18:03
add a comment |
Use the function position(substring in string)
instead of UNION, example:
WITH data(name, other_column) AS (
VALUES
('abc xyz', 1),
('xyz abc', 2),
('a xyz b', 3),
('xyz abc', 4)
)
SELECT name, other_column
FROM data
WHERE name ILIKE '%xyz%'
ORDER BY position('xyz' in name), other_column
LIMIT 100;
name | other_column
---------+--------------
xyz abc | 2
xyz abc | 4
a xyz b | 3
abc xyz | 1
(4 rows)
or:
SELECT name, other_column
FROM data
WHERE name ILIKE '%xyz%'
ORDER BY position('xyz' in name) > 1, other_column
LIMIT 100;
name | other_column
---------+--------------
xyz abc | 2
xyz abc | 4
abc xyz | 1
a xyz b | 3
(4 rows)
Use the function position(substring in string)
instead of UNION, example:
WITH data(name, other_column) AS (
VALUES
('abc xyz', 1),
('xyz abc', 2),
('a xyz b', 3),
('xyz abc', 4)
)
SELECT name, other_column
FROM data
WHERE name ILIKE '%xyz%'
ORDER BY position('xyz' in name), other_column
LIMIT 100;
name | other_column
---------+--------------
xyz abc | 2
xyz abc | 4
a xyz b | 3
abc xyz | 1
(4 rows)
or:
SELECT name, other_column
FROM data
WHERE name ILIKE '%xyz%'
ORDER BY position('xyz' in name) > 1, other_column
LIMIT 100;
name | other_column
---------+--------------
xyz abc | 2
xyz abc | 4
abc xyz | 1
a xyz b | 3
(4 rows)
edited Nov 21 '18 at 18:02
answered Nov 21 '18 at 17:57
klinklin
60.3k65686
60.3k65686
Sozxyz
will be beforeaaxyz
– forpas
Nov 21 '18 at 18:01
@forpas - Use the second variant, if it matters.
– klin
Nov 21 '18 at 18:03
add a comment |
Sozxyz
will be beforeaaxyz
– forpas
Nov 21 '18 at 18:01
@forpas - Use the second variant, if it matters.
– klin
Nov 21 '18 at 18:03
So
zxyz
will be before aaxyz
– forpas
Nov 21 '18 at 18:01
So
zxyz
will be before aaxyz
– forpas
Nov 21 '18 at 18:01
@forpas - Use the second variant, if it matters.
– klin
Nov 21 '18 at 18:03
@forpas - Use the second variant, if it matters.
– klin
Nov 21 '18 at 18:03
add a comment |
By using other_column
:
SELECT t.name FROM (
SELECT name, CONCAT(' ', name) AS other_column FROM data WHERE (name ILIKE 'xyz%')
UNION
SELECT name, name AS other_column FROM data WHERE (name ILIKE '%xyz%') AND (name NOT ILIKE 'xyz%')
) AS t
ORDER BY t.other_column
LIMIT 100;
What this does is append a prefix of blank space (ASCII 32) to name
in the first list and creates other_column
.
In the second list other_column
is the same as the name
.
Finally sorts by other_column
.
as far as I understand, the sort order is unpredictable in case of UNION without an ORDER BY clause due to the duplicate removal.
– Mad Scientist
Nov 21 '18 at 17:43
so this will make me think about it. I will delete after you read.
– forpas
Nov 21 '18 at 17:46
@MadScientist check this.
– forpas
Nov 21 '18 at 18:12
add a comment |
By using other_column
:
SELECT t.name FROM (
SELECT name, CONCAT(' ', name) AS other_column FROM data WHERE (name ILIKE 'xyz%')
UNION
SELECT name, name AS other_column FROM data WHERE (name ILIKE '%xyz%') AND (name NOT ILIKE 'xyz%')
) AS t
ORDER BY t.other_column
LIMIT 100;
What this does is append a prefix of blank space (ASCII 32) to name
in the first list and creates other_column
.
In the second list other_column
is the same as the name
.
Finally sorts by other_column
.
as far as I understand, the sort order is unpredictable in case of UNION without an ORDER BY clause due to the duplicate removal.
– Mad Scientist
Nov 21 '18 at 17:43
so this will make me think about it. I will delete after you read.
– forpas
Nov 21 '18 at 17:46
@MadScientist check this.
– forpas
Nov 21 '18 at 18:12
add a comment |
By using other_column
:
SELECT t.name FROM (
SELECT name, CONCAT(' ', name) AS other_column FROM data WHERE (name ILIKE 'xyz%')
UNION
SELECT name, name AS other_column FROM data WHERE (name ILIKE '%xyz%') AND (name NOT ILIKE 'xyz%')
) AS t
ORDER BY t.other_column
LIMIT 100;
What this does is append a prefix of blank space (ASCII 32) to name
in the first list and creates other_column
.
In the second list other_column
is the same as the name
.
Finally sorts by other_column
.
By using other_column
:
SELECT t.name FROM (
SELECT name, CONCAT(' ', name) AS other_column FROM data WHERE (name ILIKE 'xyz%')
UNION
SELECT name, name AS other_column FROM data WHERE (name ILIKE '%xyz%') AND (name NOT ILIKE 'xyz%')
) AS t
ORDER BY t.other_column
LIMIT 100;
What this does is append a prefix of blank space (ASCII 32) to name
in the first list and creates other_column
.
In the second list other_column
is the same as the name
.
Finally sorts by other_column
.
edited Nov 21 '18 at 18:40
answered Nov 21 '18 at 17:40
forpasforpas
17.8k3728
17.8k3728
as far as I understand, the sort order is unpredictable in case of UNION without an ORDER BY clause due to the duplicate removal.
– Mad Scientist
Nov 21 '18 at 17:43
so this will make me think about it. I will delete after you read.
– forpas
Nov 21 '18 at 17:46
@MadScientist check this.
– forpas
Nov 21 '18 at 18:12
add a comment |
as far as I understand, the sort order is unpredictable in case of UNION without an ORDER BY clause due to the duplicate removal.
– Mad Scientist
Nov 21 '18 at 17:43
so this will make me think about it. I will delete after you read.
– forpas
Nov 21 '18 at 17:46
@MadScientist check this.
– forpas
Nov 21 '18 at 18:12
as far as I understand, the sort order is unpredictable in case of UNION without an ORDER BY clause due to the duplicate removal.
– Mad Scientist
Nov 21 '18 at 17:43
as far as I understand, the sort order is unpredictable in case of UNION without an ORDER BY clause due to the duplicate removal.
– Mad Scientist
Nov 21 '18 at 17:43
so this will make me think about it. I will delete after you read.
– forpas
Nov 21 '18 at 17:46
so this will make me think about it. I will delete after you read.
– forpas
Nov 21 '18 at 17:46
@MadScientist check this.
– forpas
Nov 21 '18 at 18:12
@MadScientist check this.
– forpas
Nov 21 '18 at 18:12
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53417540%2funion-query-ordered-separately-by-its-components%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown