My database is like
id|service_id
1 | 8
2 | 3
3 | 4
4 | 1
5 | 3
6 | 2
7 | 1
i want to sort it like rows with same service_id came together but randomly. like
id|service_id
1 | 8
4 | 1
7 | 1
2 | 3
5 | 3
6 | 2
3 | 4
means first all rows sort via service_id then again sort via random service_id. I have tried SELECT * from sample_table order by service_id DESC and tried ASC too but it only do sort via DESC or ASC. I have tried order by rand(service_id) too but it is also showing some fixed sorting.
select t.*
from your_table t
join
(
select service_id, rand() as r
from your_table
group by service_id
) tmp on t.service_id = tmp.service_id
order by tmp.r;
SQLFiddle demo
Basically this makes a random substitute for the service_id and orders by that
Related
I have a couple of tables that I'd like to combine into one list. I have limited knowledge of what I can do with MySQL and already hit the fact that UNION needs to have the same amount of columns...
One table has data like the following:
batch_no
1
2
3
4
5
6
9
10
12
The other has
batch_no
subbatch_no
7
1
7
2
7
3
8
1
8
2
11
1
11
2
I basically want to be able to have a output that displays like this:
batch_no
1
2
3
4
5
6
7-1
7-2
7-3
8-1
8-2
9
10
11-1
11-2
12
I've had various attempts but the following is the best I came up with but obviously is sorting incorrectly...
SELECT batch_no FROM batch
UNION
SELECT CONCAT(batch_no,'-',subbatch_no) FROM subbatch
ORDER BY batch_no DESC
With this the order is seemingly being done as if it were text because I have put the hyphen in, stumped as to how to do this.
Do the ordering on the original union, adding an extra subbatch_no column to the batch subquery. Then order these together by two columns in the main query, where you can also concatenate them with the - separator.
SELECT CONCAT_WS('-', batch_no, subbatch_no) AS combined_batch_no
FROM (
SELECT batch_no, NULL AS subbatch_no
FROM batch
UNION
SELECT batch_no, subbatch_no
FROM subbatch
) AS sub1
ORDER by batch_no, subbatch_no
it is actually quite easy sorting apha numrical qith your data
SELECT CAST(batch_no as char) batchno FROM batch
UNION
SELECT CONCAT(batch_no,'-',subbatch_no) FROM subbatch
ORDER BY batchno+0 ASC
| batchno |
| :------ |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7-1 |
| 7-2 |
| 7-3 |
| 8-1 |
| 8-2 |
| 9 |
| 10 |
| 11-1 |
| 11-2 |
| 12 |
db<>fiddle here
select CONCAT_WS('-',batch_no,subbatch_no) from (
SELECT batch_no,null subbatch_no FROM batch
UNION ALL
SELECT batch_no,subbatch_no FROM subbatch
) A
ORDER BY batch_no,subbatch_no
Try with the following:
WITH cte AS (
SELECT batch_no, NULL as subbatch_no FROM tab1
UNION ALL
SELECT * FROM tab2
)
SELECT CONCAT_WS('-' , batch_no, subbatch_no) AS batch_no
FROM cte
ORDER BY cte.batch_no, cte.subbatch_no
Check the demo here.
EDIT: The goal is to order the output so that the first result is the row with store_id = 5 and the maximum rank of all items with store_id = 5. Then the rest of the deals are ranked according to their rank in descending order, regardless of their store_id. For the actual query, a union would be too expensive.
An example of data would be:
+----+----------+------+
| id | store_id | rank |
+----+----------+------+
| 1 | 1 | 10 |
+----+----------+------+
| 2 | 5 | 9 |
+----+----------+------+
| 3 | 4 | 8 |
+----+----------+------+
| 4 | 3 | 7 |
+----+----------+------+
| 5 | 3 | 6 |
+----+----------+------+
| 6 | 1 | 5 |
+----+----------+------+
The final query being run would be:
SELECT id,store_ID,IF(#id=id,rank=rank*9999999,rank) AS rank
FROM (
SELECT * FROM (
SELECT id,rank,store_id
FROM items
) b
JOIN (#id:=(SELECT id FROM b WHERE store_id = 5 ORDER BY rank DESC LIMIT 1)) AS s
)
ORDER BY rank DESC
And the desired outcome would be:
+----+----------+------+
| id | store_id | rank |
+----+----------+------+
| 2 | 5 | 9 |
+----+----------+------+
| 1 | 1 | 10 |
+----+----------+------+
| 3 | 4 | 8 |
+----+----------+------+
| 4 | 3 | 7 |
+----+----------+------+
| 5 | 3 | 6 |
+----+----------+------+
| 6 | 1 | 5 |
+----+----------+------+
Here (#id:=(SELECT id FROM b WHERE store_id = 5 ORDER BY rank DESC LIMIT 1)) is being used to select the top scoring item with store_id = 5. This item is meant to appear first in the list, hence why it is reranked by multiplying it by a very large number. All other ranks remain untouched and are ranked according to their score in descending order.
The problem is that the select statement in the join is trying to join a selection from a subquery called b. However, table b does not actually exist in the database, so MySQL is saying that table b does not exist. How can I reference the subquery? The actual subquery is incredibly complex, so I haven't included it here, but if interested you can see a version of it here: MySQL - How To Optimize thie Query. The query in this question is just to keep the problem simple.
You can adjust your order by clause to put a specific row first. Let's say you wanted store_id 5 to be first, you can do this:
ORDER BY store_id = 5 DESC, rank DESC;
Which will put the row with store_id 5 on top. In this example, you want the row that has the highest rank for store_id 5, so I wrote the following subquery:
SELECT id
FROM myTable
WHERE store_id = 5
ORDER BY rank DESC
LIMIT 1;
And I put that in the ORDER BY clause:
SELECT *
FROM myTable
ORDER BY id =
(SELECT id FROM myTable WHERE store_id = 5 ORDER BY rank DESC LIMIT 1) DESC,
rank DESC;
Here is an SQL Fiddle.
EDIT
If you put a subquery in your FROM clause, you won't be able to reference its alias in the subquery of the ORDER BY clause. However, in a very unreadable fashion, you can put the same subquery there to accomplish it, like this:
SELECT *
FROM (SELECT * FROM myTable) b
ORDER BY id =
(SELECT id FROM (SELECT * FROM myTable) b WHERE store_id = 5 ORDER BY rank DESC LIMIT 1) DESC,
rank DESC;
Another Fiddle.
Just to post here if someone will have the same problem.
Table:
id | idp | ids
---+-----+-----
5 | 2 | 5
4 | 1 | 4
3 | 3 | 3
2 | 2 | 2
1 | 4 | 1
I set the GROUP BY idp ORDER BY id "didn't" affect results. I was trying to get last 10 rows grouped by idp sorted by id or ids. The problem is that last (first in table) row was grouped with forth row, and order was different.
SQL that works:
SELECT idp, MAX(ids) AS max_ids
FROM table
GROUP BY idp
ORDER BY max_ids DESC
LIMIT 0,10
If I have a table with the following structure and data:
id | user_id | created_at
-------------------------
1 | 7 | 0091942
2 | 3 | 0000014
3 | 6 | 0000890
4 | 6 | 0029249
5 | 7 | 0000049
6 | 3 | 0005440
7 | 9 | 0010108
What query would I use to get the following results (explanation to follow):
id | user_id | created_at
-------------------------
1 | 7 | 0091942
6 | 3 | 0005440
4 | 6 | 0029249
7 | 9 | 0010108
As you can see:
Only one row per user_id is returned.
The row with the highest created_at is the one returned.
Is there a way to accomplish this without using subqueries? Is there a name in relational algebra parlance that this procedure goes by?
The query is known as a groupwise maximum, which (in MySQL, at least) can be implemented with a subquery. For example:
SELECT my_table.* FROM my_table NATURAL JOIN (
SELECT user_id, MAX(created_at) created_at
FROM my_table
GROUP BY user_id
) t
See it on sqlfiddle.
You can just get the max and group by the user_id:
select id,user_id,max(created_at)
from supportContacts
group by user_id
order by id;
Here is what it outputs:
ID USER_ID MAX(CREATED_AT)
1 7 91942
2 3 5440
3 6 29249
7 9 10108
See the working demo here
Note that the example on the fiddle uses the created_at field as int, just use your format it should make no difference.
EDIT: I will leave this answer as a referece but note that his query will produce undesired results as Gordon stated, please do not use this in production.
I have the next example table:
id | user_id | data
-------------------
1 | 1 | 10
2 | 2 | 10
3 | 2 | 10
4 | 1 | 10
5 | 3 | 10
6 | 4 | 10
7 | 4 | 10
8 | 5 | 10
9 | 5 | 10
10 | 2 | 10
11 | 6 | 10
12 | 3 | 10
13 | 1 | 10
I need to create a SELECT query, that LIMITS my data. For example, I have a limit range (1, 3) (page number = 1, row count = 3). It should selects rows with first 3 unique user_id. And if there are some rows in the end of table with this first user_id's, they should be included to the result. LIMIT statement is bad for this query, because I can get more than 3 rows. Output for my limit should be:
id | user_id | data
-------------------
1 | 1 | 10
2 | 2 | 10
3 | 2 | 10
4 | 1 | 10
5 | 3 | 10
10 | 2 | 10
12 | 3 | 10
13 | 1 | 10
Can you help me to generate this query?
How about:
SELECT *
FROM table
WHERE user_id IN
(SELECT distinct(user_id) FROM table order by user_id LIMIT 3);
What about something like this?
SELECT * FROM table WHERE user_id BETWEEN (number) AND (number+row count)
I know it isn't working but you should be able to make it work ^^
The sample code below can be used for Oracle & Mysql. (use TOP for SQL Server & Sybase)
You get all the results from your table (t1) that match the top 3 user_id (t2) (check the MySQL manual for the limit function)
SELECT *
FROM exampletable t1
INNER JOIN (
SELECT DISTINCT user_id
FROM exampletable
ORDER BY user_id
LIMIT 0,3 -- this is the important part
) AS t2 ON t1.user_id = t2.user_id
ORDER BY id
For the next 3 id's change the limit 0,3 to limit 3,6.