SQL - UNION does not order second SELECT - mysql
I`m trying to solve this challenge:
https://www.hackerrank.com/challenges/the-pads
My solution is this in MySQL:
(SELECT CONCAT(Name,'(',SUBSTR(Occupation,1,1),')') FROM Occupations ORDER BY Name)
UNION
(SELECT CONCAT('There are total ', COUNT(Occupation), ' ',LOWER(Occupation),'s.') AS total FROM Occupations
GROUP BY Occupation
ORDER BY total);
However it fails to ORDER BY total.
Ashley(P)
Samantha(A)
Julia(D)
Britney(P)
Maria(P)
Meera(P)
Priya(D)
Priyanka(P)
Jennifer(A)
Ketty(A)
Belvet(P)
Naomi(P)
Jane(S)
Jenny(S)
Kristeen(S)
Christeen(S)
Eve(A)
Aamina(D)
There are total 4 actors.
There are total 3 doctors.
There are total 7 professors.
There are total 4 singers.
If I only run
SELECT CONCAT('There are total ', COUNT(Occupation), ' ',LOWER(Occupation),'s.') AS total FROM Occupations
GROUP BY Occupation
ORDER BY total
it does order:
There are total 3 doctors.
There are total 4 actors.
There are total 4 singers.
There are total 7 professors.
The result gets ordered by the final ORDER BY clause. This is ORDER BY total, i.e. by the first column. (You only give this name in the second part of UNION, which would probably not work in another DBMS. You should name the columns you select in a UNION query in the first part.)
You want to get names first, then the aggregates. Then you want names alphabetically, aggregates by count (i.e. not alphabetically, not 1 -> 10 -> 11 -> 2 -> 20 ..., but 1 -> 2 -> 10 -> 11 -> 20 ...) then by job name. You can create sortkeys for this task. I assume you really want UNION ALL, not UNION. If I am wrong, change it :-)
SELECT txt
FROM
(
SELECT
CONCAT(Name, '(', SUBSTR(Occupation, 1, 1), ')') as txt,
1 as sortkey1,
CONCAT(Name, '(', SUBSTR(Occupation, 1, 1), ')') as sortkey2
FROM Occupations
UNION ALL
SELECT
CONCAT('There are total ', COUNT(Occupation), ' ', LOWER(Occupation), 's.') AS txt,
2 + COUNT(Occupation) as sortkey1,
LOWER(Occupation) as sortkey2
FROM Occupations
GROUP BY Occupation
) data
ORDER BY sortkey1, sortkey2;
That is correct. The ordering of the result set is based only on the outermost order by. This is true for union as for other operations.
(SELECT CONCAT(Name,'(', SUBSTR(Occupation,1,1),')') AS total
FROM Occupations
ORDER BY Name
)
UNION ALL
(SELECT CONCAT('There are total ', COUNT(Occupation), ' ', LOWER(Occupation), 's.') AS total
FROM Occupations
GROUP BY Occupation
)
ORDER BY (CASE WHEN total LIKE 'There are total%' THEN 1 ELSE 0 END),
Total;
This assumes that Name never starts with 'There are total', which seems likely.
#gordon answer is fine
But for a more generic case you have to create a "dummy" field to separate each group.
(SELECT CONCAT(Name,'(', SUBSTR(Occupation,1,1),')') as Name,
0 as dummy
FROM Occupations
)
UNION ALL
(SELECT CONCAT('There are total ', COUNT(Occupation), ' ', LOWER(Occupation), 's.') AS Name,
1 as dummy
FROM Occupations
GROUP BY Occupation
)
ORDER BY dummy, name
Based on the answers and my best understanding I came with this solution that works for this case:
(SELECT CONCAT(Name,'(',SUBSTR(Occupation,1,1),')') as total FROM Occupations ORDER BY Name)
UNION ALL
(SELECT CONCAT('There are total ', COUNT(Occupation), ' ',LOWER(Occupation),'s.') AS total FROM Occupations
GROUP BY Occupation)
ORDER BY total;
This worked for me.
you can give two different select queries whith out UNION/ UNION ALL.
SELECT Concat(NAME, '(', Substr(occupation, 1, 1), ')') AS Result
FROM occupations
ORDER BY NAME;
SELECT Concat('There are a total of ', Count(*), ' ', Lower(occupation), 's.')
FROM occupations
GROUP BY occupation
ORDER BY Count(*), occupation;
Related
How to print each value of the query result obtained from grouping
SELECT DISTINCT OCCUPATION, COUNT(*) FROM OCCUPATIONS GROUP BY OCCUPATION ORDER BY COUNT(*), OCCUPATION ASC; Above query will give me unique Occupation and their count in ascending order of their occurrence. Now I want to use the result to print statement There are a total of [occupation_count] [occupation]s. I tried this SELECT CONCAT('There are a total of ', COUNT(*), DISTINCT OCCUPATION, 's.') FROM OCCUPATIONS GROUP BY OCCUPATION ORDER BY COUNT(*), OCCUPATION ASC; but I got syntax error. for each distinct occupation. How can I do this? Should I write a subquery?
DISTINCT is almost never needed in a query that uses GROUP BY, so your query doesn't require it. So just use: SELECT CONCAT('There are a total of ', COUNT(*), ' ', OCCUPATION, 's.') FROM OCCUPATIONS GROUP BY OCCUPATION ORDER BY COUNT(*), OCCUPATION ASC; Note that SELECT DISTINCT is a single keyword -- like LEFT JOIN or IS NULL. Nothing is supposed to go between the keywords.
mysql when UNION display [Err] 1111 - Invalid use of group function
I do a sql oj on hackerrank. I need to first order people with name and order occupation with corresponding count. Database table like the png image display table structure. I want to use select type from ( ( SELECT name as type, 1 as filter FROM occupations order by name ) UNION All ( select concat(count(occupation), ' ', lower(occupation), 's.') as type, 2 as filter FROM occupations group by occupation order by count(occupation) ) ) result order by filter, type to solve this question, but get "[Err] 1111 - Invalid use of group function". If I comment order by count(occupation) could be okay. Or just use select concat(count(occupation), ' ', lower(occupation), 's.') as type, 2 as filter FROM occupations group by occupation order by count(occupation) is also okay, but once union would receive this error ( SELECT name as type, 1 as filter FROM occupations order by name ) UNION All ( select concat(count(occupation), ' ', lower(occupation), 's.') as type, 2 as filter FROM occupations group by occupation order by count(occupation) ) but I copy this union to postgresql(change string contract function) is okay, no this error.postgresql is okay In mysql, I must to convert this "order by count(occupation)" set to another temporary table to solve this error, like this: select type from ( (SELECT concat(name, '(', LEFT(occupation , 1), ')') as type, 1 as filter FROM occupations order by name) UNION All (select * from ( select concat('There are a total of ', count(occupation), ' ', lower(occupation), 's.') as type, 2 as filter FROM occupations group by occupation order by count(occupation) ) result) ) last order by filter, type I am very confused, very appreciate your help!
order by is invalid within unions. Move the order by outside of the union operation.
Keep ORDER BY after UNION [duplicate]
This question already has answers here: How can I order entries in a UNION without ORDER BY? (7 answers) Closed 4 years ago. I have a problem to solve. I have a table Occupationswith Name and Occupation. My task is to: 1.Query an alphabetically ordered list of all names in OCCUPATIONS, immediately followed by the first letter of each profession as a parenthetical (i.e.: enclosed in parentheses). For example: AnActorName(A), ADoctorName(D), AProfessorName(P), and ASingerName(S). query the number of ocurrences of each occupation in OCCUPATIONS. Sort the occurrences in ascending order, and output them in the following format: There are a total of [occupation_count] [occupation]s. If more than one Occupation has the same they should be ordered alphabetically. I am almost done with the query SELECT TEMP.CON1 FROM ( SELECT NAME, CONCAT(NAME,'(', LEFT(OCCUPATION, 1),')') AS CON1 FROM OCCUPATIONS ORDER BY NAME ) AS TEMP UNION SELECT TEMP2.CON2 FROM ( SELECT COUNT(*) AS NR, CONCAT('THERE ARE A TOTAL OF ', COUNT(OCCUPATION),' ', OCCUPATION, 's') AS CON2 FROM OCCUPATIONS GROUP BY OCCUPATION ORDER BY NR, OCCUPATION ) AS TEMP2 but I don't know how to keep the order of the first section after the two sections are united. If anyone knows the answer I would be superglad for sharing.
SELECT CON FROM ( SELECT 1 as SEQ, 0 as NR, NAME ,TEMP.CON1 as CON FROM ( SELECT NAME, CONCAT(NAME,'(', LEFT(OCCUPATION, 1),')') AS CON1 FROM OCCUPATIONS ORDER BY NAME -- don't need ) AS TEMP UNION SELECT 2, NR, null, TEMP2.CON2 FROM ( SELECT COUNT(*) AS NR, CONCAT('THERE ARE A TOTAL OF ', COUNT(OCCUPATION),' ', OCCUPATION, 's') AS CON2 FROM OCCUPATIONS GROUP BY OCCUPATION ORDER BY NR, OCCUPATION -- don't need ) AS TEMP2 ) T ORDER BY SEQ, NR, NAME, CON
UNION ALL would keep the order, and would work just as well in this case as your result sets are totally different. The difference between union and union all is that UNION removes duplicates, which causes reordering, where UNION ALL simply adds the next set of results to the end of the existing result set. Since you are manipulating the strings on both selects, there is no real chance of there being duplicates in the results between TEMP and TEMP2. This will also get rid of some of the cost of the query, since UNION is more expensive than UNION ALL, as it needs to check for duplicates. SELECT TEMP.CON1 FROM ( SELECT NAME, CONCAT(NAME,'(', LEFT(OCCUPATION, 1),')') AS CON1 FROM OCCUPATIONS ORDER BY NAME ) AS TEMP UNION ALL SELECT TEMP2.CON2 FROM ( SELECT COUNT(*) AS NR, CONCAT('THERE ARE A TOTAL OF ', COUNT(OCCUPATION),' ', OCCUPATION, 's') AS CON2 FROM OCCUPATIONS GROUP BY OCCUPATION ORDER BY NR, OCCUPATION ) AS TEMP2 This being said, the way I read the instructions, I wouldn't expect both results to be desired in the same result set.
MySQL Join Query Autogenerate Serial Number
My Following Query gives the result according to my record but what i have the problem is my query is generating some different serial number .Anyways i need the serial number to start from 1 but this query is join query is shows different serial number like i can say during joining it skips the series . Kindly help to generate the series from 1 to number of rows from db without skipping the series in between. Thanks in Advance SELECT #a:=#a+1 sno, p.po_no as id, DATE_FORMAT(p.po_date, '%d-%m-%Y') as po_date, p.customer, p.cust_po as po_no, p.tot_ord_qty, DATE_FORMAT(p.delivery_date, '%d-%m-%Y') AS delivery_date, p.dc_status, p.inv_status, p.tot_dc_qty, p.tot_inv_qty, COALESCE(GROUP_CONCAT(distinct d.dc_no SEPARATOR ', '), 0) as dc, GROUP_CONCAT( d.active SEPARATOR ', ') as status FROM (SELECT #a:= 0) AS a, po_header p LEFT JOIN dc_details d ON p.cust_po = d.cust_po group by p.cust_po Result:
The reason you're skipping numbers is because of GROUP BY. Grouping is done after the serial numbers are generated, so it combines all the rows with the same cust_po and you only see one of the serial numbers. Move the grouping into a subquery and add the serial numbers in the main query. SELECT #a := #a+1 AS sno, t.* FROM (SELECT #a := 0) AS a CROSS JOIN ( SELECT p.po_no as id, DATE_FORMAT(p.po_date, '%d-%m-%Y') as po_date, p.customer, p.cust_po as po_no, p.tot_ord_qty, DATE_FORMAT(p.delivery_date, '%d-%m-%Y') AS delivery_date, p.dc_status, p.inv_status, p.tot_dc_qty, p.tot_inv_qty, COALESCE(GROUP_CONCAT(distinct d.dc_no SEPARATOR ', '), 0) as dc, GROUP_CONCAT( d.active SEPARATOR ', ') as status FROM po_header AS p LEFT JOIN dc_details AS d ON p.cust_po = d.cust_po GROUP BY p.cust_po ORDER BY p.cust_po) AS t
MySQL Query error using UNION/UNION ALL and Group By
Generate the following two result sets: 1). Query an alphabetically ordered list of all names in OCCUPATIONS, immediately followed by the first letter of each profession as a parenthetical (i.e.: enclosed in parentheses). For example: AnActorName(A), ADoctorName(D), AProfessorName(P), and ASingerName(S). 2). Query the number of ocurrences of each occupation in OCCUPATIONS. Sort the occurrences in ascending order, and output them in the following format: There are total [occupation_count] [occupation]s. Table Name: Occupations Total Columns: Two = 'Name' and 'Occupation', demo table is shown below: Sample Output: Ashely(P) Christeen(P) Jane(A) Jenny(D) Julia(A) Ketty(P) Maria(A) Meera(S) Priya(S) Samantha(D) There are total 2 doctors. There are total 2 singers. There are total 3 actors. There are total 3 professors. My Approach: (SELECT NAME, '(', SUBSTRING(OCCUPATION, 1, 1), ')' FROM OCCUPATIONS ORDER BY NAME) UNION ALL (SELECT COUNT(*) FROM OCCUPATIONS GROUP BY OCCUPATION ORDER BY ASEC); Error: ERROR 1222 (21000) at line 1: The used SELECT statements have a different number of columns Thank You!
Sometimes on HackerRank concat functon will give an error. You can use || to seperate in the same way. So if the code below doesnt work for you: ( SELECT CONCAT(NAME, '(', SUBSTRING(OCCUPATION, 1, 1), ')') as THETEXT, '1' as SELECTNUMBER FROM OCCUPATIONS ) UNION ALL ( SELECT CONCAT('There are total ', COUNT(*),' ', OCCUPATION, (IF (COUNT(*) > 1, 's',''))) as THETEXT, '2' as SELECTNUMBER FROM OCCUPATIONS GROUP BY OCCUPATION ) ORDER BY SELECTNUMBER ASC, THETEXT ASC; TRY THIS INSTEAD! SELECT name || '(' || UPPER(SUBSTR(occupation, 1, 1)) || ')' FROM occupations ORDER BY name; SELECT 'There are a total of' || ' ' || COUNT(occupation) || ' ' || LOWER(occupation) || 's' || '.' FROM occupations GROUP BY occupation ORDER BY COUNT(occupation) ASC;
I just tried on hackerrank and it works, You don't need to use Union. select concat(name,'(',upper(substring(occupation,1,1)),')') from occupations order by name; select concat("There are a total of",' ',count(occupation),' ',lower(occupation),'s',".") from occupations group by occupation order by count(occupation) asc;
SELECT concat(NAME,concat("(",LEFT(occupation,1),")")) FROM OCCUPATIONS ORDER BY NAME ASC; select CONCAT("There are a total of", " ",COUNT(occupation), " ",LCASE(occupation),"s",".")AS stat from OCCUPATIONS group by occupation order by COUNT(occupation) ASC,occupation
Worked on hackerrank SELECT Name || '(' || SUBSTR(Occupation,1,1) || ')'-- AS THETEXT, '1' AS SELECTNUMBER FROM OCCUPATIONS order by Name; SELECT 'There are a total of' || ' ' || COUNT(*) || ' ' || lower(Occupation) || 's.' FROM OCCUPATIONS GROUP BY OCCUPATION ORDER BY COUNT(Occupation), lower(Occupation);
union requires the two queries have the same number of columns, you can add any some columns to the second query to make them like the first one like SELECT COUNT(*), 'col-1', 'col-2', 'col-3' from
//Just be careful for the format! (select concat(name, '(',left(occupation,1),')') as text from occupations ) union all ( select concat( 'There are total ', count(*), ' ', lower(occupation), case when COUNT(*) > 1 then 's' end , '.' ) as text from occupations group by occupation ) order by text asc;
( SELECT CONCAT(NAME, '(', SUBSTRING(OCCUPATION, 1, 1), ')') as THETEXT FROM OCCUPATIONS ) UNION ALL ( SELECT CONCAT('There are total ', COUNT(*),' ', LOWER(OCCUPATION) ,(IF (COUNT(*) > 1, 's','')), '.') as THETEXT FROM OCCUPATIONS group by OCCUPATION ) ORDER by THETEXT ASC;
This worked for me on MySQL select concat(name,"(",substr(occupation,1,1),")") from occupations order by name asc; select concat('There are total ',count(*),' ',lower(occupation),'s.') as n from occupations group by occupation order by n asc;
select concat(name,'(',left(occupation,1),')') from occupations order by name; select concat('There are total of',' ',count(occupation),' ',lower(occupation),"s.") from occupations group by occupation order by count(occupation),occupation;
(Select name||'('||substr(Occupation,0,1)||')' from OCCUPATIONS) Union All (Select 'There are a total of '||count(*)||' '||lower(Occupation)||'s.' from OCCUPATIONS group by Occupation) order by 1;
SELECT CONCAT(name, '(', SUBSTRING(occupation, 1, 1), ')') as occ from occupations ORDER BY name; SELECT concat('There are a total of ', COUNT(*), ' ', LCASE(occupation), 's.') from occupations GROUP BY occupation ORDER BY COUNT(*), occupation; This does the charm.
SELECT CONCAT(NAME ,'('||SUBSTR(occupation,1,1)||')') FROM occupations ORDER BY NAME ASC; SELECT CONCAT('There are a total of ',COUNT (occupation)||' '||LOWER(occupation)||'s.') FROM occupations GROUP BY occupation ORDER BY COUNT(occupation),occupation ASC;
This works for me: select CONCAT(name,'(',left(occupation,1),')') from OCCUPATIONS order by name; select CONCAT('There are a total of',' ',count(occupation),' ',lower(occupation),'s.') from OCCUPATIONS group by occupation order by count(occupation), occupation;
SELECT CONCAT(NAME,'(',LEFT(OCCUPATION,1),')') FROM OCCUPATIONS ORDER BY NAME; SELECT CONCAT("There are total of ",COUNT_OCCUPATION," ",OCCUPATION,".") FROM (SELECT COUNT(OCCUPATION) AS COUNT_OCCUPATION,OCCUPATION FROM OCCUPATIONS GROUP BY OCCUPATION ORDER BY COUNT_OCCUPATION ASC,OCCUPATION ASC) AS OCP
select CONCAT(NAME, '(', left(OCCUPATION,1),')') from OCCUPATIONS ORDER BY NAME; select CONCAT("There are a total of ", count(OCCUPATION), " ", lower(OCCUPATION),(if(count(OCCUPATION) >1,"s","")), ".") from OCCUPATIONS group by occupation order by count(OCCUPATION), OCCUPATION;
select concat(name, '(',substring(occupation,1,1),')') from OCCUPATIONS order by name; select concat('There are a total of ',count(occupation),' ',lower(occupation),'s.') as 'sentence' from OCCUPATIONS group by occupation order by count(occupation), occupation,field(occupation,'doctor','singer','actor','professor');
check below code. hope this helps its 100% working select concat(Name,"(",left(Occupation,1),")") from occupations order by Name; select concat("There are a total of ",count(Occupation),' ',lower(occupation),"s.") from Occupations group by occupation order by count(Occupation)asc, Occupation;
/* sort answer is here */ ( select concat(name,'(',left(occupation,1),')') as ocps from Occupations) union (select distinct concat('There are a total of ',count(occupation),' ',lower(occupation),'s.') from Occupations group by occupation)order by ocps;
select Name+'('+substring(Occupation,1,1)+')' from occupations order by name asc; select concat('There are a total of',' ', count(occupation),' ',Lower(occupation),'s','.') from Occupations group by Occupation order by count(occupation), occupation asc
One can make use of the UNION operator in MySQL to union each part of the question. NOTE: To combine the column names into one column the CONCAT() function can be used. SELECT DISTINCT CONCAT(name, '(', left(occupation, 1), ')') AS n from OCCUPATIONS union select concat('There are a total of ', (select count(*) from OCCUPATIONS group by occupation having occupation = 'doctor'), ' doctors.') union select concat('There are a total of ', (select count(*) from OCCUPATIONS group by occupation having occupation = 'singer'), ' singers.') union select concat('There are a total of ', (select count(*) from OCCUPATIONS group by occupation having occupation = 'actor'), ' actors.') union select concat('There are a total of ', (select count(*) from OCCUPATIONS group by occupation having occupation = 'professor'), ' professors.') order by n asc;
select concat(Name,'(',substring(Occupation,1,1),')') from OCCUPATIONS order by Name; select concat('There are a total of ',count(*),' ',LCASE(Occupation), If(count(*)>1,'s.','')) from OCCUPATIONS group by Occupation order by count(*) ASC ;
Please follow this code for Mysql. This works best for me. I have tried and got the correct results. select concat(name,'(',left(occupation,1),')') from occupations order by name; select concat('There are a total of ',count,' ',lower(occupation),'s.') from (select occupation, count(*) as count from occupations group by occupation)a order by count, occupation; For first query, I have concat the column 'name' with brackets and 1st char of value in column occupation. later order by is arranging them in ascending order (by default it is in ascending order). second query, order by count(occupation) was not working for me so to solve this, i have used nested queries. Query in bracket is providing me occupation column, count of occupation when it is group by. then i concat the string with count and occupation name. later order by count in ascending order. Further if count is same for 2 occupations , so used order by occupation too to arrange them in ascending order. Thanks
SELECT concat(name,'(',left(occupation,1),')') FROM occupations ORDER BY name; SELECT concat('There are a total of ',cnt,' ',lower(occupation),'s.') FROM ( SELECT occupation,count(occupation) as cnt FROM occupations GROUP BY occupation ) a ORDER BY cnt,occupation;
You can use in this way: SELECT CONCAT(NAME,"(",SUBSTRING(Occupation, 1, 1),")") FROM OCCUPATIONS ORDER BY NAME SELECT CONCAT("There are a total of"," ",COUNT(Occupation), " ",LOWER(Occupation),"s",".") FROM OCCUPATIONS GROUP BY Occupation ORDER BY COUNT(Occupation),Occupation
This works too, no need of union as they are asking for 2 separate queries select name||'('||substr(occupation,1,1)||')' from occupations order by name; select 'There are a total of ',cnt,decode(occ,'P','professors','D','doctors', 'S','singers','A','actors')||'.' from (select distinct(substr(occupation,1,1)) as occ,count(*) as cnt from occupations group by substr(occupation,1,1)) order by cnt,occ;
select concat(name,"(",substring(occupation, 1, 1), ")") from occupations order by name; select concat("There are a total of ", count(Occupation), " ", lower(occupation), "s.") from occupations group by occupation order by count(Occupation), Occupation;
select concat(Name,'(',upper(substr(Occupation,1,1)),')') from OCCUPATIONS order by Name; select concat('There are a total of',' ',count(Occupation),' ',lower(Occupation),'s','.') from OCCUPATIONS group by Occupation order by count(Occupation) asc,lower(Occupation); P.S--- LOOK AT THE SECOND QUERY...ADD A FULLSTOP
This works on Hacker rank, check this out (select concat(name,'(',substr(occupation,1,1),')') N from OCCUPATIONS) union (select concat('There are a total of ',count(occupation),' ',lower(occupation),'s.') from occupations group by occupation) order by N asc;
WITH t1 AS (SELECT name, LEFT(occupation,1) AS firstletter FROM occupations ORDER BY 1) SELECT CONCAT(name, '(', firstletter, ')') AS result FROM t1; WITH t2 AS (SELECT occupation, COUNT(occupation) AS occupation_count FROM occupations GROUP BY 1 ORDER BY 2,1) SELECT CONCAT('There ','are ','a ','total ','of ',occupation_count,' ' ,LOWER(occupation),'s','.') FROM t2; I have broken the question down into two CTE(Common table expression) which are temporary tables. The first CTE(t1) selects the occupation table for name, selects the first letter of the data in occupation column using "LEFT()" function then orders alphabetically by name as required by the question. The select statement then queries the CTE(t1) using "CONCAT()" function to obtain its result. CTE(t2) selects occupation, "COUNT()", group by occupation and order by occupation count and occupation. the select statement then queries t2 using "CONCAT()"
SELECT CONCAT(NAME,"(",LEFT(OCCUPATION,1),")") FROM OCCUPATIONS ORDER BY NAME; SELECT CONCAT("There are a total of ",COUNT(OCCUPATION)," ",lower(OCCUPATION),"s.") FROM OCCUPATIONS GROUP BY OCCUPATION ORDER BY COUNT(OCCUPATION);