Two columns town and priority.
I need to sort table, so that towns with priority=1 would be first and not sorted by name ASC, while the rest gets sorted by name ASC.
How would i do that?
Thanks ;)
Update
SELECT *
FROM map_towns
ORDER BY priority DESC, town
Like this, but so that priority were from 1 to 12+ instead of 12 to 1.
Like that:
town priority
b_town1 1
a_town2 2
d_town3 3
c_town4 4
a_town5 NULL
b_town6 NULL
c_town7 NULL
d_town8 NULL
etc...
By default, MySQL sorts nulls first
I created a small test case (rows inserted non-sorted on purpose).
create table map_towns(
town varchar(30) not null
,priority int null
);
insert into map_towns(town, priority) values('d_town3', 3);
insert into map_towns(town, priority) values('a_town2', 2);
insert into map_towns(town, priority) values('c_town4', 4);
insert into map_towns(town, priority) values('b_town1', 1);
insert into map_towns(town, priority) values('b_town6', NULL);
insert into map_towns(town, priority) values('d_town8', NULL);
insert into map_towns(town, priority) values('a_town5', NULL);
insert into map_towns(town, priority) values('c_town7', NULL);
The following query should do what you ask for.
select town
,priority
,isnull(priority)
from map_towns
order by isnull(priority), priority, town;
+---------+----------+------------------+
| town | priority | isnull(priority) |
+---------+----------+------------------+
| b_town1 | 1 | 0 |
| a_town2 | 2 | 0 |
| d_town3 | 3 | 0 |
| c_town4 | 4 | 0 |
| a_town5 | NULL | 1 |
| b_town6 | NULL | 1 |
| c_town7 | NULL | 1 |
| d_town8 | NULL | 1 |
+---------+----------+------------------+
Here is a link on ISNULL documentation
My idea:
SELECT * FROM Towns
ORDER BY IF(priority = 1, 0, 1) ASC,
town ASC;
Well just simply make it so that the Priority by default is 0, and then each Town you have you can sort them based on a number. I would normally do something like DisplayOrder which in terms could be your Priority.
something like this.
SELECT * FROM Towns
ORDER BY priority ASC,
name ASC;
So if you have something like
id, name, priority
-----------------------
1, Smithtown, 0
2, Rocktown, 2
3, Georgetown, 1
4, Rockton, 2
The ordering then would be
1, Smithtown, 0
3, Georgetown, 1
4, Rockton, 2
2, Rocktown, 2
SELECT *
FROM map_towns
ORDER BY
priority IS NULL, priority, town
Related
I'm really not sure how to exactly phrase what I'm looking to do therefore I'm having trouble searching. I have a table of pages that each have an id, title, order and parent_id if the parent_id is NULL that's considered a top level page. I'm able to almost sort this correctly with ORDER BY by parent_id and order with the following query:
select `id`, `title`, `order`, `parent_id`
from pages
order by `order` AND COALESCE(`parent_id`, `order`), `parent_id` is not null, `order`
The query spits out the following:
id
title
order
parent_id
107fa138
video
0
NULL
8eeda86c
mn
2
NULL
cac640ad
xxe title
3
NULL
1ce4d070
sdfsdfsdf
4
NULL
b45dc24d
another
1
8eeda86c
d3490141
hello
9
8eeda86c
This is almost what I want. Ideally, I'd have the rows with parent_ids directly under the row with that id so ideally the sort order would look like this:
id
title
order
parent_id
107fa138
video
0
NULL
8eeda86c
mn
2
NULL
b45dc24d
another
1
8eeda86c
d3490141
hello
9
8eeda86c
cac640ad
xxe title
3
NULL
1ce4d070
sdfsdfsdf
4
NULL
I don't even know how I would go about this. If someone can point me in the right direction that would be very awesome.
I think your problem is here:
order by `order` AND COALESCE(`parent_id`, `order`), ...
This probably isn't doing what you think it's doing. The AND is a boolean operator, so it will be as if you had written this expression:
order by (`order` > 0) AND (COALESCE(`parent_id`, `order`) > 0), ...
That is, if both order and the other term are nonzero, then 1, else 0.
I think the following would get closer to what you describe:
order by COALESCE(`parent_id`, `id`),
`parent_id` is not null,
`order`
Demo:
create table pages ( id varchar(10) primary key, title text, `order` int, parent_id varchar(10) );
insert into pages (id, title, `order`, parent_id) values
('107fa138', 'video', 0, NULL),
('8eeda86c', 'mn', 2, NULL),
('cac640ad', 'xxe title', 3, NULL),
('1ce4d070', 'sdfsdfsdf', 4, NULL),
('b45dc24d', 'another', 1, '8eeda86c'),
('d3490141', 'hello', 9, '8eeda86c');
select `id`, `title`,
COALESCE(parent_id, id) as cpi,
parent_id is not null as pinn,
`order`,
`parent_id`
from pages
order by COALESCE(`parent_id`, `id`), `parent_id` is not null, `order`
+----------+-----------+----------+------+-------+-----------+
| id | title | cpi | pinn | order | parent_id |
+----------+-----------+----------+------+-------+-----------+
| 107fa138 | video | 107fa138 | 0 | 0 | NULL |
| 1ce4d070 | sdfsdfsdf | 1ce4d070 | 0 | 4 | NULL |
| 8eeda86c | mn | 8eeda86c | 0 | 2 | NULL |
| b45dc24d | another | 8eeda86c | 1 | 1 | 8eeda86c |
| d3490141 | hello | 8eeda86c | 1 | 9 | 8eeda86c |
| cac640ad | xxe title | cac640ad | 0 | 3 | NULL |
+----------+-----------+----------+------+-------+-----------+
By adding in the columns that show the sorting expressions we can see how the sort occurs.
First it sorts by cpi alphabetically. This prefers the parent_id if it is set, but defaults to id.
For ties of cpi, then it sorts by pinn. So 0 comes before 1.
For ties of pinn (i.e. when multiple rows have a value 1), then it sorts by order.
Is this not what you wanted?
I'm pretty new to SQL and am currently trying to run a query which will return the total count of a value under a certain limit (using phpmyadmin).
Say we've got a table like so:
CarID | Car | OwnerID
-------------------
1 | Name | 1
2 | Name | 3
3 | Name | 2
4 | Name | 1
Now I would like to be able to get the total count of cars a owner has if it's under let's say 2 - to then get this:
OwnerID| TotalCars |
---------------------
2 | 1 |
3 | 1 |
How would I accomplish this? My situation is slightly different than the example I gave but it's fundamentally the same exact goal but just different numbers and more records.
When I try, those with more than the number I wish to see return with zero as their value??
(My code)
Code giving me trouble
(My result)
ID 6 has 3 properties so it shouldn't be showing me it at all and I don't understand why it's returning it as 0
You can use GROUP BY COUNT and HAVING
CREATE TABLE Table1
(`CarID` int, `Car` varchar(4), `OwnerID` int)
;
INSERT INTO Table1
(`CarID`, `Car`, `OwnerID`)
VALUES
(1, 'Name', 1),
(2, 'Name', 3),
(3, 'Name', 2),
(4, 'Name', 1)
;
SELECT `OwnerID`, COUNT(*) as countr
FROM Table1
GROUP BY `OwnerID`
HAVING countr < 2
OwnerID | countr
------: | -----:
3 | 1
2 | 1
db<>fiddle here
CREATE TABLE table_1 (
`userid` VARCHAR(2),
`date_accessed` DATE,
`rank` INT,
`country` VARCHAR(2)
);
INSERT INTO table_1
(`userid`, `date_accessed`, `rank`, `country`)
VALUES
('A.', '2019-01-01', 1, 'US'),
('B.', '2019-01-02', 1, 'FR'),
('A.', '2019-01-03', 2, 'US'),
('A.', '2019-01-04', 3, 'US'),
('B.', '2019-01-04', 2, 'FR');
Fiddle: https://www.db-fiddle.com/f/caFeo5c4Try1q7FawHN7MC/1
My dataset looks like this:
user | date | rank | state
A. |2020-01-01 | 1 | NY
A. |2020-01-04 | 2 | NY
A. |2020-01-08 | 3 | NY
B. |2020-01-01 | 1 | CA
B. |2020-01-02 | 2 | CA
B. |2020-01-04 | 3 | CA
This is the product of a bunch of WITH intermediate_table AS statements — but at this point in my query this is the structure I'm working with.
For each user, I want to subtract the date ranked 1 with the date ranked 2. So for user A, I want to get the DATEDIFF between 1/1 and 1/4. Ideally the output would look like this:
user | date_diff | state
A. | 3 | NY
B. | 1 | CA
The eventual goal is to get the average date_diff for each country, averaged across all the users for that country.
For this sample data one way to do it is to GROUP BY user, state and use conditional aggregation to subtract the dates:
SELECT
user,
DATEDIFF(
MAX(CASE WHEN `rank` = 2 THEN date END),
MAX(CASE WHEN `rank` = 1 THEN date END)
) date_diff,
state
FROM tablename
WHERE `rank` IN (1, 2)
GROUP BY user, state
See the demo.
Results:
> user | date_diff | state
> :--- | --------: | :----
> A. | 3 | NY
> B. | 1 | CA
I have the below table, that stores the rank of person participating in respective events.
event_running and event_jumping are the events and the ranks stored.
CREATE TABLE `ranks` (
`id` int(11) NOT NULL,
`personid` int(11) NOT NULL,
`event_running` int(11) DEFAULT NULL,
`event_longjump` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Sample data
INSERT INTO `ranks` (`id`, `personid`, `event_running`, `event_longjump`) VALUES
(1, 1, 4, 8),
(2, 2, 10, 6),
(3, 3, 5, 0),
(4, 5, 20, 1),
(5, 4, 9, 3),
(6, 6, 1, 2);
SQL Fiddle Link
I want to build a leaderboard as below
| Standing | PersonID | RunningRank | JumpingRank |
| 1 | 6 | 1 | 2 |
| 2 | 4 | 9 | 3 |
| 3 | 1 | 4 | 8 |
| 4 | 3 | 5 | 0 |
| 5 | 2 | 10 | 6 |
This has to be sorted in ascending order - irrespective of the events lowest come first and also ranks above 20 are ignored.
And inputs on how can this be done?
you can use something similar to below
select PersonID,
RunningRank,
JumpingRank,
(RunningRank + JumpingRank) as Total
from ranks
order by Total asc
limit 20;
Here's your query.
set #row_number = 0;
select (#row_number:=#row_number + 1) as standing, personid, event_running, event_longjump from ranks
where event_running < 20 and event_longjump < 20
order by
case when if(event_longjump=0,event_running ,event_longjump) < event_running
then event_longjump else event_running end
see dbfiddle
Your sorting criteria is a bit vague. I am assuming that you want to sort on the basis of cumulative of the ranks across all events and its jumping score.
Also, please explain the position of person Id 3 in your queation.
You can do,
select PersonID,
RunningRank,
JumpingRank,
(JumpingRank + RunningRank) as cumulativeRank
from ranks
ORDER BY cumulativeRank, JumpingRank aesc
limit 20;
This will get you all the positions baring person id 3
I have to put down the lines that have two distinct fields with value = 0
Let me explain, all records that have stock_it=0 and stock_eu=0 must go to the bottom of the results
I have used this solution, however, it is not strictly correct because it puts down even rows that do not have both values = 0
$dati = mysql_query("
SELECT *
FROM $tb_article
ORDER BY
FIELD($tb_art.article_status,'n') DESC,
FIELD($tb_art.article_stock_it,'0') ASC,
FIELD($tb_art.article_stock_eu,'0') ASC,
$tb_art.article_rank
");
article_status=n indicates new products and they have to stay on top!
Push to bottom all the article that have stock IT and stock EU = 0 (products not available)
In the end, order the rest of the articles according to the rank assigned
You can use the CASE statement in ORDER BY, like this:
SELECT *
FROM $tb_article
ORDER BY
CASE WHEN article_status = 'n' THEN 0
WHEN article_stock_it = 0 THEN 100000
WHEN article_stock_eu = 0 THEN 100000
ELSE article_rank
END
If you want to use ORDER BY FIELD :
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE tb_article
(
article_stock_it int,
article_stock_eu int,
article_status varchar(11),
article_rank int
);
INSERT INTO tb_article VALUES
(1, 1, 'n', 1)
, (0, 1, 'n', 1)
, (0, 0, 'n', 1)
, (1, 1, 'o', 1)
, (1, 1, 'o', 2);
Query 1:
SELECT *
FROM tb_article
ORDER BY
FIELD(tb_article.article_status,'n') DESC,
FIELD(
IF(tb_article.article_stock_it = 0 AND tb_article.article_stock_eu = 0,'1','0')
,'0') DESC,
tb_article.article_rank
Results:
| article_stock_it | article_stock_eu | article_status | article_rank |
|------------------|------------------|----------------|--------------|
| 1 | 1 | n | 1 |
| 0 | 1 | n | 1 |
| 0 | 0 | n | 1 |
| 1 | 1 | o | 1 |
| 1 | 1 | o | 2 |