SORT ACCESS UNION QUERY SQL - ms-access

I applied a union query in this data
DRAW NO C1 C2 C3 C4 C5 C6 C7 C8
DWG-1 D D C C A A B B
DWG-2 B B A
Using this sql
SELECT [DRAW NO], [C1] AS Data FROM Query2
UNION SELECT [DRAW NO], [C2] FROM Query2
UNION SELECT [DRAW NO], [C3] FROM Query2
UNION SELECT [DRAW NO], [C4] FROM Query2
UNION SELECT [DRAW NO], [C5] FROM Query2
UNION SELECT [DRAW NO], [C6] FROM Query2
UNION SELECT [DRAW NO], [C7] FROM Query2
UNION SELECT [DRAW NO], [C8] FROM Query2;
And the results is like this
DRAW NO DATA
DWG-1 A
DWG-1 B
DWG-1 C
DWG-1 D
DWG-2 A
DWG-2 B
Is it possible to change the output to this kind of sorting?
DRAW NO DATA
DWG-1 D
DWG-1 C
DWG-1 A
DWG-1 B
DWG-2 B
DWG-2 A
Edit from the OP's comment:
I need to get the value of c1 first.. then c2.. if c2 has duplicates c3 should be the next value and so on.

You can use plain SQL for this:
SELECT [DRAW NO], [C1] AS Data FROM Query2
UNION
SELECT [DRAW NO], [C2] FROM Query2
UNION
SELECT [DRAW NO], [C3] FROM Query2
UNION
SELECT [DRAW NO], [C4] FROM Query2
UNION
SELECT [DRAW NO], [C5] FROM Query2
UNION
SELECT [DRAW NO], [C6] FROM Query2
UNION
SELECT [DRAW NO], [C7] FROM Query2
UNION
SELECT [DRAW NO], [C8] FROM Query2
ORDER BY
[Data]="D", [Data]="C", [Data]="A", [Data]="B";
Official documentation: Use a union query to combine multiple queries into a single result

For your sample data this will work:
SELECT t.[DRAW NO], t.Data FROM (
SELECT [DRAW NO], 1 AS col, [C1] AS Data FROM Query2 UNION
SELECT [DRAW NO], 2, [C2] FROM Query2 UNION
SELECT [DRAW NO], 3, [C3] FROM Query2 UNION
SELECT [DRAW NO], 4, [C4] FROM Query2 UNION
SELECT [DRAW NO], 5, [C5] FROM Query2 UNION
SELECT [DRAW NO], 6, [C6] FROM Query2 UNION
SELECT [DRAW NO], 7, [C7] FROM Query2 UNION
SELECT [DRAW NO], 8, [C8] FROM Query2
) AS t
WHERE t.[Data] IS NOT NULL
GROUP BY t.[DRAW NO], t.Data
ORDER BY t.[DRAW NO], MIN(t.col)
Results:
DRAW NO Data
DWG-1 D
DWG-1 C
DWG-1 A
DWG-1 B
DWG-2 B
DWG-2 A

Related

Insert unique random number with recursive MySQL

I want to populate a table with unique random numbers without using a procedure.
I've tried using this reply to do it but not success.
What I'm trying to do is something like this but validating that numbers are not repeated:
INSERT into table (row1,row2)
WITH RECURSIVE
cte AS ( SELECT 0 num, LPAD(FLOOR(RAND() * 99999999),8,0) random_num
UNION ALL
SELECT num+1, LPAD(FLOOR(RAND() * 99999999),8,0) random_num
FROM cte WHERE num < 100000-1)
SELECT random_num, null
FROM cte;
In the example above, I am able to generate random values and insert them but without validating that the numbers are not repeated.
I have tried to do this:
INSERT into table (row1,row2)
WITH RECURSIVE
cte AS ( SELECT 0 num, LPAD(FLOOR(RAND() * 99999999),8,0) random_num
UNION ALL
SELECT num+1, LPAD(FLOOR(RAND() * 99999999),8,0) random_num
FROM cte WHERE num < 100000-1 AND random_num NOT IN (SELECT random_num FROM cte WHERE random_num IS NOT NULL))
SELECT random_num, null
FROM cte;
but the condition AND random_num NOT IN (SELECT random_num FROM cte WHERE random_num IS NOT NULL) in the where case, causes an SQL Error [4008] [HY000]: Restrictions imposed on recursive definitions are violated for table 'cte'
Any suggestions of how to do it? thank you!.
This could be an option. Generate all possible values, sort randomly and take desired number of entries.
CREATE TABLE random_data (
row1 INT PRIMARY KEY AUTO_INCREMENT,
row2 VARCHAR(10) NOT NULL,
UNIQUE KEY _Idx1 ( row2 )
);
INSERT INTO random_data (row2)
SELECT LPAD(num, 8, 0)
FROM (
SELECT h * 10000000 + g * 1000000 + f * 100000 + e * 10000 + d * 1000 + c * 100 + b * 10 + a AS num
FROM (SELECT 0 a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) ta
JOIN (SELECT 0 b UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) tb
JOIN (SELECT 0 c UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) tc
JOIN (SELECT 0 d UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) td
JOIN (SELECT 0 e UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) te
JOIN (SELECT 0 f UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) tf
JOIN (SELECT 0 g UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) tg
JOIN (SELECT 0 h UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) th
) n
ORDER BY RAND()
LIMIT 100000;
If you have a table - any table - with e.g. 100 rows then you can generate million distinct random numbers between 0 and 99999999 as follows:
select distinct floor(rand() * 100000000)
from t as t0, t as t1, t as t2
limit 1000000
Note that because of distinct you will need to generate a bigger number of rows so that you get desired number of rows after distinct.

How do I fetch limited data sets for a different values on a singles column?

Suppose I've Table T and It has 3 Columns and 3rd Column contains 10 distinct values and I want to fetch 5 samples from Table T for each distinct value in column 3rd.
WITH T(A, B,C) AS(
SELECT 12,'Hi','One' FROM DUAL UNION ALL
SELECT 34,'Am','One' FROM DUAL UNION ALL
SELECT 6,'to','Two' FROM DUAL UNION ALL
SELECT 3,'do','Two' FROM DUAL UNION ALL
SELECT 5,'aim','Two' FROM DUAL UNION ALL
SELECT 6,'mine','Two' FROM DUAL UNION ALL
SELECT 4,'not','Three' FROM DUAL
)
select a,b,c from(
SELECT A,B,C,ROW_NUMBER() OVER(PARTITION BY c ORDER BY C DESC) AS R
FROM T)
where r = 1
or you could possibly try this:
SELECT MIN(T.A),
T.B,
t.c
FROM t
JOIN (SELECT C,
MAX(b) AS b
FROM T
GROUP BY C) Y ON Y.C = T.C
AND Y.B = T.B
GROUP BY t.c, t.b

Check which IDs from a set do not exists in a table

I have a list of user IDs, like this:
757392,733602,749955,744304,746852,753904,755117,636163,564931,740787,751450,743799,643918,
749903,571888,30207,705953,749120,749001,749192,749978,750840,544228,702121,746246,383667,
558790,585628,592771,745818,749375,241209,749235,746860,748318,748016,748951,747321,748684,
748225,565375,748673,747869,748522,748335,744775,672229,578056,713127,740234,632608,711135,
746528,362131,742223,746567,745224,332989,439837,745418,673582,269584,742606,745135,746950,
476134,740830,742949,276934
I have a MySQL table users with the id field.
How do I check - using a query - which IDs of the ones I have do not exists in the users table?
This sounds like a simple problem to me, yet I couldn't find any example on StackOverflow which would address a fixed set of ID values.
I didn't know the find_in_set() function and took a more handcrafted approach. Not that it makes any sense given the first answer, but I'll post it anyway:
SELECT id
FROM (
SELECT '757392' AS id UNION
SELECT '733602' UNION
SELECT '749955' UNION
SELECT '744304' UNION
SELECT '746852' UNION
SELECT '753904' UNION
SELECT '755117' UNION
SELECT '636163' UNION
SELECT '564931' UNION
SELECT '740787' UNION
SELECT '751450' UNION
SELECT '743799' UNION
SELECT '643918' UNION
SELECT '749903' UNION
SELECT '571888' UNION
SELECT '30207' UNION
SELECT '705953' UNION
SELECT '749120' UNION
SELECT '749001' UNION
SELECT '749192' UNION
SELECT '749978' UNION
SELECT '750840' UNION
SELECT '544228' UNION
SELECT '702121' UNION
SELECT '746246' UNION
SELECT '383667' UNION
SELECT '558790' UNION
SELECT '585628' UNION
SELECT '592771' UNION
SELECT '745818' UNION
SELECT '749375' UNION
SELECT '241209' UNION
SELECT '749235' UNION
SELECT '746860' UNION
SELECT '748318' UNION
SELECT '748016' UNION
SELECT '748951' UNION
SELECT '747321' UNION
SELECT '748684' UNION
SELECT '748225' UNION
SELECT '565375' UNION
SELECT '748673' UNION
SELECT '747869' UNION
SELECT '748522' UNION
SELECT '748335' UNION
SELECT '744775' UNION
SELECT '672229' UNION
SELECT '578056' UNION
SELECT '713127' UNION
SELECT '740234' UNION
SELECT '632608' UNION
SELECT '711135' UNION
SELECT '746528' UNION
SELECT '362131' UNION
SELECT '742223' UNION
SELECT '746567' UNION
SELECT '745224' UNION
SELECT '332989' UNION
SELECT '439837' UNION
SELECT '745418' UNION
SELECT '673582' UNION
SELECT '269584' UNION
SELECT '742606' UNION
SELECT '745135' UNION
SELECT '746950' UNION
SELECT '476134' UNION
SELECT '740830' UNION
SELECT '742949' UNION
SELECT '276934') AS id_list
WHERE id NOT IN (
SELECT id
FROM users);
This is an option:
SELECT ids.id
FROM ( SELECT #i
, substring(#string, #start, #end-#start) id
FROM <BigTable>
, ( SELECT #string := <YourStringOfIds>
, #start:=0
, #end:=0
, #i:=0
, #len:=length(#string)
, #n:=#len-length(replace(#string,',',''))+1
) t
WHERE (#i := #i+1) <= #n
AND (#start := #end+1)
AND (#loc := locate(',',#string,#start))
AND #end := if(#loc!=0,#loc,#len+1)
) ids
LEFT JOIN <BigTable> u
ON u.id = ids.id
WHERE u.id is null
BigTable can be any table whose number of rows >= number of ids in your string.
Create temporary table, then fill it
CREATE TABLE tmp (
`id` INT NOT NULL,
PRIMARY KEY (`id`));
INSERT INTO tmp (id) VALUES (1),(2),(3),(4),(5),(6)
then make a query
SELECT tmp.id
FROM tmp
LEFT JOIN users u ON u.id = tmp.id
WHERE tmp.id IS NULL
finally drop the table
DROP TABLE tmp
You're looking for the IN clause with a negation. I.e. you can specify your list as the argument to the IN clause like so:
SELECT * FROM users
WHERE id NOT IN ( 757392,733602,749955,744304,746852,753904,755117,636163,564931,740787,751450,743799,643918,749903,571888,30207,705953,749120,749001,749192,749978,750840,544228,702121,746246,383667,558790,585628,592771,745818,749375,241209,749235,746860,748318,748016,748951,747321,748684,748225,565375,748673,747869,748522,748335,744775,672229,578056,713127,740234,632608,711135,746528,362131,742223,746567,745224,332989,439837,745418,673582,269584,742606,745135,746950,476134,740830,742949,276934 );
UPDATE
My bad - I didn't read the question properly.
So the correct way would be to go with UNIONs then outer join and filter by NULL, like this:
SELECT WantedIds.id
FROM users
RIGHT JOIN (
SELECT x.id
FROM (
SELECT '757392' AS id UNION
SELECT '733602' UNION
SELECT '749955' UNION
SELECT '744304' UNION
SELECT '746852' UNION
SELECT '753904' UNION
SELECT '755117' UNION
SELECT '636163' UNION
SELECT '564931' UNION
.
.
.
) x
) WantedIds
ON WantedIds.id = users.id
WHERE users.id IS NULL
You can use MySQL's find_in_set() function to check if a value exists in a commase separated list of values:
select * from your_table
where find_in_set(field_name,'757392,733602,749955,744304,746852,753904,755117,636163,564931,740787,751450')=0

MYSQL select count of distinct values from comma separated

How can I select the distinct values and relative count from data that is stored as comma separated values in MySql?
This is how the data in the table looks like:
"Category" "Values"
"red" "D,A,D,D"
"yellow" "A,A,D,D"
Desire Output:
"red" "D" "3"
"red" "A" "1"
"yellow" "D" "2"
"yellow" "A" "2"
Can you think of a good way in mysql to get output like the way I've done?
Thank's in advance.
Using a derived table you can split the string into rows
SELECT `Category`, SUBSTRING_INDEX(SUBSTRING_INDEX(t.`Values`, ',', n.n), ',', -1) `value`
FROM table1 t CROSS JOIN
(
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
ORDER BY n
) n
WHERE n.n <= 1 + (LENGTH(t.`Values`) - LENGTH(REPLACE(t.`Values`, ',', '')))
Then just GROUP BY and COUNT
DEMO
SELECT `Category`, `value`, COUNT(*) as cnt
FROM (
<previous query>
) T
GROUP BY `Category`, `value`

MYSQL Query: combine columns and get count

I have about 9 tables that contain the same type of field. I would like to combine the 9 of them FIRST, and then get the distinct count of unique values in that combined column. This is what I've tried so far, but to no avail. I'm not also not sure this is the most efficient way to return this value?
SELECT COUNT(DISTINCT aircraft_id) FROM
(
SELECT aircraft_id FROM database.a_message UNION ALL
SELECT aircraft_id FROM database.b_message UNION ALL
SELECT aircraft_id FROM database.c_message UNION ALL
SELECT aircraft_id FROM database.d_message UNION ALL
SELECT aircraft_id FROM database.e_message UNION ALL
SELECT aircraft_id FROM database.f_message UNION ALL
SELECT aircraft_id FROM database.g_message UNION ALL
SELECT aircraft_id FROM database.h_message UNION ALL
SELECT aircraft_id FROM database.i_message
) ;
SELECT DISTINCT aircraft_id,count(aircraft_id) FROM
(
SELECT aircraft_id FROM database.a_message UNION ALL
SELECT aircraft_id FROM database.b_message UNION ALL
SELECT aircraft_id FROM database.c_message UNION ALL
SELECT aircraft_id FROM database.d_message UNION ALL
SELECT aircraft_id FROM database.e_message UNION ALL
SELECT aircraft_id FROM database.f_message UNION ALL
SELECT aircraft_id FROM database.g_message UNION ALL
SELECT aircraft_id FROM database.h_message UNION ALL
SELECT aircraft_id FROM database.i_message
) group by aircraft_id;
or
select aircraft_id,count(aircraft_id)
(
SELECT DISTINCT aircraft_id FROM
(
SELECT aircraft_id FROM database.a_message UNION ALL
SELECT aircraft_id FROM database.b_message UNION ALL
SELECT aircraft_id FROM database.c_message UNION ALL
SELECT aircraft_id FROM database.d_message UNION ALL
SELECT aircraft_id FROM database.e_message UNION ALL
SELECT aircraft_id FROM database.f_message UNION ALL
SELECT aircraft_id FROM database.g_message UNION ALL
SELECT aircraft_id FROM database.h_message UNION ALL
SELECT aircraft_id FROM database.i_message
)
) group by aircraft_id;