how to order by <= 7 desc then by > 7 asc? - mysql

in my table https://www.db-fiddle.com/f/4yPorU6k3SjQ5nmhgi1wGo/0
i use query
SELECT id
FROM test
ORDER BY id <= 7 DESC, id DESC
i want to order everything from 7 to lesser by the bigger then everything else by the lesser
my query give me
| id |
| --- |
| 6 |
| 3 |
| 2 |
| 1 |
| 65 |
| 35 |
| 34 |
| 33 |
| 12 |
| 11 |
| 11 |
| 10 |
but i want to give me
| id |
| --- |
| 6 |
| 3 |
| 2 |
| 1 |
| 10 |
| 11 |
| 11 |
| 12 |
| 33 |
| 34 |
| 35 |
| 65 |

Consider a conditional sort, like so:
select id
from test
order by
case when id <= 7 then id end desc,
id
Demo on DB Fiddle:
| id |
| -: |
| 6 |
| 3 |
| 2 |
| 1 |
| 10 |
| 11 |
| 11 |
| 12 |
| 33 |
| 34 |
| 35 |
| 65 |

I think you want:
SELECT id
FROM test
ORDER BY id <= 7 DESC,
(CASE WHEN id <= 7 THEN id END) DESC,
id ASC

Related

select and group by same value mysql

i have table with data like this below
| id | wallet_id | wallet_name | deposit | |
|----|-----------|-------------|---------|---|
| 1 | 12 | a_wallet | 10 | |
| 2 | 14 | c_wallet | 12 | |
| 3 | 12 | a_wallet | 24 | |
| 4 | 15 | e_wallet | 50 | |
| 5 | 14 | c_wallet | 10 | |
| 6 | 15 | e_wallet | 22 | |
i want to select and group with same wallet_id, probably something like this
| wallet_id | id | wallet_name |
|-----------|----|-------------|
| 12 | 1 | a_wallet |
| | 3 | a_wallet |
| 14 | 2 | c_wallet |
| | 5 | c_wallet |
| 15 | 4 | e_wallet |
| | 6 | e_wallet |
i already try
select wallet_id, id, wallet_name from wallet group by wallet_id
but it shows like usual select query with no grouping.
Kindly need your help, thanks
We would generally handle your requirement from the presentation layer (e.g. PHP), but if you happen to be using MySQL 8+, here is a way to do this directly from MySQL:
SELECT
CASE WHEN ROW_NUMBER() OVER (PARTITION BY wallet_id ORDER BY id) = 1
THEN wallet_id END AS wallet_id,
id,
wallet_name
FROM wallet w
ORDER BY w.wallet_id, id;

Picking out specific values from a group in MySQL

This seems like such a simple problem, but I can't find a good solution. I'm trying to select information from a slightly misformatted table. Basically, wherever sequence=0, the person_id should actually be a company_id. This company_id then applies to all the rows which have the same group_id.
Someone thought it was a good idea to format things this way instead of simply having a company_id column, but it makes trying to select by company very difficult. It would make my programming much easier to simply add this extra column, and fix the formatting.
I want to turn something like this:
+----------+------------+-----------+----------+
| group_id | date | person_id | sequence |
+----------+------------+-----------+----------+
| 1 | 2012-08-31 | 10 | 0 |
| 1 | 2012-08-31 | 11 | 1 |
| 1 | 2012-08-31 | 12 | 2 |
| 2 | 1999-04-16 | 10 | 0 |
| 2 | 1999-04-16 | 21 | 1 |
| 2 | 1999-04-16 | 22 | 2 |
| 2 | 1999-04-16 | 23 | 3 |
| 2 | 1999-04-16 | 24 | 4 |
| 3 | 2001-01-09 | 30 | 0 |
| 3 | 2001-01-09 | 31 | 1 |
| 3 | 2001-01-09 | 11 | 2 |
| 3 | 2001-01-09 | 12 | 3 |
+----------+------------+-----------+----------+
Into this:
+------------+----------+------------+-----------+----------+
| company_id | group_id | date | person_id | sequence |
+------------+----------+------------+-----------+----------+
| 10 | 1 | 2012-08-31 | 11 | 1 |
| 10 | 1 | 2012-08-31 | 12 | 2 |
| 10 | 2 | 1999-04-16 | 21 | 1 |
| 10 | 2 | 1999-04-16 | 22 | 2 |
| 10 | 2 | 1999-04-16 | 23 | 3 |
| 10 | 2 | 1999-04-16 | 24 | 4 |
| 30 | 3 | 2001-01-09 | 31 | 1 |
| 30 | 3 | 2001-01-09 | 11 | 2 |
| 30 | 3 | 2001-01-09 | 12 | 3 |
+------------+----------+------------+-----------+----------+
The only way I can think of how to achieve this is with nested SELECT statements, which are very inefficient considering I have about 100M rows. It's a one time fix though, so I don't mind letting it run overnight.
If you permanently want to change your table to include a company_id column then do this:
First alter the table and add the new column:
alter table your_table add company_id int;
Then update all rows to set the company to the person_id = 0 for the group:
UPDATE your_table a
JOIN your_table b ON a.group_id = b.group_id
SET a.company_id = b.person_id
WHERE b.sequence = 0;
And finally remove the rows with sequence = 0:
DELETE FROM your_table WHERE sequence = 0;
Sample SQL Fiddle
The end result will be:
| group_id | date | person_id | sequence | company_id |
|----------|------------|-----------|----------|------------|
| 1 | 2012-08-31 | 11 | 1 | 10 |
| 1 | 2012-08-31 | 12 | 2 | 10 |
| 2 | 1999-04-16 | 21 | 1 | 10 |
| 2 | 1999-04-16 | 22 | 2 | 10 |
| 2 | 1999-04-16 | 23 | 3 | 10 |
| 2 | 1999-04-16 | 24 | 4 | 10 |
| 3 | 2001-01-09 | 31 | 1 | 30 |
| 3 | 2001-01-09 | 11 | 2 | 30 |
| 3 | 2001-01-09 | 12 | 3 | 30 |

How can I order multiple columns in mysql?

I have this table in my mysql:
| id | category_id | region_id | score |
+----+-------------+-----------+-------+
| 1 | 1 | 1 | 78 |
| 2 | 1 | 2 | 65 |
| 3 | 1 | 3 | 98 |
| 4 | 1 | 4 | 45 |
| 5 | 1 | 5 | 78 |
| 6 | 1 | 1 | 98 |
| 7 | 1 | 2 | 32 |
| 8 | 1 | 3 | 56 |
| 9 | 1 | 4 | 89 |
| 10 | 1 | 5 | 65 |
+----+-------------+-----------+-------+
I want to get the 5 latest id but order my result table base on region id so I used this code
SELECT *
FROM tb_scores
WHERE category_id = 1
ORDER
BY id DESC
, region_id ASC
LIMIT 5
but the result only sorted the id as desc but not the region_id as ASC..to explain briefly I want this kind of result.
| id | category_id | region_id | score |
+----+-------------+-----------+-------+
| 6 | 1 | 1 | 98 |
| 7 | 1 | 2 | 32 |
| 8 | 1 | 3 | 56 |
| 9 | 1 | 4 | 89 |
| 10 | 1 | 5 | 65 |
+----+-------------+-----------+-------+
try this:
SELECT *
FROM (SELECT *
FROM tb_scores
WHERE category_id = 1
ORDER BY id DESC,region_id ASC LIMIT 5) t
ORDER BY region_id
get your data in subquery and apply order by region_id on the subquery result.

MySQL - How to use GROUP BY / ORDER BY with "nested" dataset?

My (sub)query results in following dataset:
+---------+------------+-----------+
| item_id | version_id | relevance |
+---------+------------+-----------+
| 1 | 1 | 30 |
| 1 | 2 | 30 |
| 2 | 3 | 22 |
| 3 | 4 | 30 |
| 4 | 5 | 18 |
| 3 | 6 | 30 |
| 2 | 7 | 22 |
| 1 | 8 | 30 |
| 5 | 9 | 48 |
| 4 | 10 | 18 |
| 5 | 11 | 48 |
| 3 | 12 | 30 |
| 3 | 13 | 31 |
| 4 | 14 | 19 |
| 2 | 15 | 22 |
| 1 | 16 | 30 |
| 5 | 17 | 49 |
| 2 | 18 | 22 |
+---------+------------+-----------+
18 rows in set (0.00 sec)
Items and versions are stored in separate InnoDB-tables.
Both tables have auto-incrementing primary keys.
Versions have a foreign key to items (item_id).
My question: How do I get a subset based on relevance?
I would like to fetch the following subset containing the most relevant versions:
+---------+------------+-----------+
| item_id | version_id | relevance |
+---------+------------+-----------+
| 1 | 16 | 30 |
| 2 | 18 | 22 |
| 3 | 13 | 31 |
| 4 | 14 | 19 |
| 5 | 17 | 49 |
+---------+------------+-----------+
It would be even more ideal to fetch the MAX(version_id) in case of equal relevance.
I tried grouping, joining, ordering, etcetera in many ways but I'm not able to get the desired result.
Some of the things I tried is:
SELECT item_id, version_id, relevance
FROM (subquery) a
GROUP BY item_id
ORDER BY relevance DESC, version_id DESC
But of course the ordering happens after the fact, so that both relevance and MAX(version_id) information is lost.
Please advice.
This is how you can do this:
SELECT t1.item_id, max(t1.version_id), t1.relevance FROM t t1
LEFT JOIN t t2 ON t1.item_id = t2.item_id AND t1.relevance < t2.relevance
WHERE t2.relevance IS NULL
GROUP BY t1.item_id
ORDER BY t1.item_id, t1.version_id
Output:
| ITEM_ID | VERSION_ID | RELEVANCE |
|---------|------------|-----------|
| 1 | 16 | 30 |
| 2 | 18 | 22 |
| 3 | 13 | 31 |
| 4 | 14 | 19 |
| 5 | 17 | 49 |
Fiddle here.

join with a group by?

i have a table called rc_language_type_table with:
id language
1 english
2 Xhosa
3 afrikaans
etc
then i have a table rc_language_type_assoc_table with:
profile_id | language_type_id |
+------------+------------------+
| 3 | 1 |
| 13 | 1 |
| 15 | 1 |
| 16 | 1 |
where i have profiles and each profile is connected to a language id in a 1 to many
so then i did:
select *,count(*) from rc_language_type_assoc_table group by language_type_id;
+------------+------------------+----------+
| profile_id | language_type_id | count(*) |
+------------+------------------+----------+
| 3 | 1 | 96 |
| 3 | 2 | 19 |
| 3 | 3 | 18 |
| 64 | 4 | 51 |
| 94 | 5 | 10 |
| 37 | 6 | 26 |
| 3 | 7 | 21 |
| 3 | 8 | 4 |
| 3 | 9 | 6 |
| 88 | 10 | 4 |
| 3 | 11 | 3 |
+------------+------------------+----------+
what i want now is: instead having the language_type_id i want to display the actual language...how would i do this please???
i tried:
select *, count(*)
from rc_language_type_assoc_table, rc_language_type_table
group by language_type_id
where rc_language_type_assoc_table.language_type_id = rc_language_type_table.id;
but i get a syntax error...
please help??
thank you
GROUP BY should be "after" the WHERE statement and not before
select *, count(*)
from rc_language_type_assoc_table, rc_language_type_table
where rc_language_type_assoc_table.language_type_id = rc_language_type_table.id
group by language_type_id ;