SQL - How to Order By in UNION query - sql

Is there a way to union two tables, but keep the rows from the first table appearing first in the result set? However orderby column is not in select query
For example:
Table 1
name surname
-------------------
John Doe
Bob Marley
Ras Tafari
Table 2
name surname
------------------
Lucky Dube
Abby Arnold
Result
Expected Result:
name surname
-------------------
John Doe
Bob Marley
Ras Tafari
Lucky Dube
Abby Arnold
I am bringing Data by following query
SELECT name,surname FROM TABLE 1 ORDER BY ID
UNION
SELECT name,surname FROM TABLE 2
The above query is not keeping track of order by after union.
P.S - I dont want to show ID in my select query
I am getting ORDER BY Column by joining tables. Following is my real query
SELECT tbl_Event_Type_Sort_Orders.Appraisal_Event_Type_ID AS Appraisal_Event_Type_ID , ISNULL(tbl_Appraisal_Event_Types.Appraisal_Event_Type_Display_Name, 'UnCategorized') AS Appraisal_Event_Type_Display_Name
INTO #temptbl
FROM tbl_Event_Type_Sort_Orders
INNER JOIN tbl_Appraisal_Event_Types
ON tbl_Event_Type_Sort_Orders.Appraisal_Event_Type_ID = tbl_Appraisal_Event_Types.Appraisal_Event_Type_ID
WHERE 1=1
AND User_Name='abc'
ORDER BY tbl_Event_Type_Sort_Orders.Sort_Order
SELECT * FROM #temptbl
UNION
SELECT DISTINCT (tbl_Appraisal_Event_Types.Appraisal_Event_Type_ID) AS Appraisal_Event_Type_ID , ISNULL(tbl_Appraisal_Event_Types.Appraisal_Event_Type_Display_Name, 'UnCategorized') AS Appraisal_Event_Type_Display_Name
FROM tbl_Appraisal_Event_Types
INNER JOIN tbl_Appraisal_Events
ON tbl_Appraisal_Event_Types.Appraisal_Event_Type_ID = tbl_Appraisal_Events.Event_Type_ID
INNER JOIN tbl_Appraisals
ON tbl_Appraisal_Events.Appraisal_ID = tbl_Appraisal_Events.Appraisal_ID
WHERE 1=1
AND ((tbl_Appraisals.Assigned_To_Staff_User) = 'abc' OR (tbl_Appraisals.Assigned_To_Staff_User2) = 'abc' OR (tbl_Appraisals.Assigned_To_Staff_User3) = 'abc')

Put a UNION ALL in a derived table. To keep duplicate elimination, do select distinct and also add a NOT EXISTS to second select to avoid returning same person twice if found in both tables:
select name, surname
from
(
select distinct name, surname, 1 as tno
from table1
union all
select distinct name, surname, 2 as tno
from table2 t2
where not exists (select * from table1 t1
where t2.name = t1.name
and t2.surname = t1.surname)
) dt
order by tno, surname, name

You can use a column for the table and one for the ID to order by:
SELECT x.name, x.surname FROM (
SELECT ID, TableID = 1, name, surname
FROM table1
UNION ALL
SELECT ID = -1, TableID = 2, name, surname
FROM table2
) x
ORDER BY x.TableID, x.ID

You can write as below, if you are ok with duplicate data then please use UNION ALL it will be faster:
SELECT NAME, surname FROM (
SELECT ID,name,surname FROM TABLE 1
UNION
SELECT ID,name,surname FROM TABLE 2 ) t ORDER BY ID

this will order the first row sets first then by anything you need
(haven't tested the code)
;with cte_1
as
(SELECT ID,name,surname,1 as table_id FROM TABLE 1
UNION
SELECT ID,name,surname,2 as table_id FROM TABLE 2 )
SELECT name, surname
FROM cte_1
ORDER BY table_id,ID

simply use a UNION clause with out order by.
SELECT name,surname FROM TABLE 1
UNION
SELECT name,surname FROM TABLE 2
if you wanted to order first table use the below query.
;WITH cte_1
AS
(SELECT name,surname,ROW_NUMBER()OVER(ORDER BY Id)b FROM TABLE 1 )
SELECT name,surname
FROM cte_1
UNION
SELECT name,surname
FROM TABLE 2

Related

Select number of IDs in more than one table (from three tables)

I need the count of this:
select distinct ID
from (
select ID from A
union all
select ID from B
union all
select ID from C
) ids
GROUP BY ID HAVING COUNT(*) > 1;
but I have no idea how to do it.
Use a subquery:
select count(*)
from (select ID
from (select ID from A
union all
select ID from B
union all
select ID from C
) ids
group by ID
having count(*) > 1
) i;
SELECT DISTINCT is almost never needed with GROUP BY and definitely not in this case.
You just want to find the id that appear 2 more times in the A,B,C table, the SQL is below:
select count(1) from (
select
id,
count(1)
from
(
select ID from A
union all
select ID from B
union all
select ID from C
)
group by id having(count(1)>1)
) tmp

I have a table without any primary key and i want it all duplicate records

I have a table without any primary key and I want it all duplicate records
Table --
EmpName City
-------------
Shivam Noida
Ankit Delhi
Mani Gurugram
Shivam Faizabad
Mukesh Noida
and want output like this --
EmpName City
-------------
Shivam Noida
Shivam Faizabad
Mukesh Noida
Thanks in Advance.
I think you want exists:
select t.*
from t
where exists (select 1
from t t2
where (t2.empname = t.empname and t2.city <> t.city) or
(t2.city = t.city and t2.empname <> t.empname)
);
You seem to be looking for all rows where the name or city also appears in another row of the table.
select *
from mytable
where city in (select city from mytable group by city having count(*) > 1)
or empname in (select empname from mytable group by empname having count(*) > 1);
You say there is no primary key. This suggests that there can be duplicate rows (same name and city). This makes it impossible in many DBMS to use EXISTS here to look up the other rows. This is why I am suggesting IN and COUNT.
use exists and or condition
with cte as
(
select 'Shivam' as name, 'Noida' as city union all
select 'Ankit' , 'Delhi' union all
select 'Mani' , 'Gurugram' union all
select 'Shivam' , 'Faizabad' union all
select 'Mukesh' , 'Noida'
) select t1.* from cte t1 where exists ( select 1 from cte t2
where t1.name=t2.name
group by name
having count(*)>1
)
or exists
(
select 1 from cte t2
where t1.city=t2.city
group by city
having count(*)>1
)
output
name city
Shivam Noida
Shivam Faizabad
Mukesh Noida
Do a UNION ALL to put both types of names in one column. (d1)
GROUP BY its result, and use HAVING to return only duplicates (d2).
JOIN:
select EmpName, City
from tablename t1
join (select name from
(select EmpName name from tablename
union all
select City from tablename) d1
group by name
having count(*) > 1) d2
on d2.name in (EmpName, City)
select distinct * from table
where col1 in (select col1 from table group by col1 having count(1) > 1)
or col2 in (select col2 from table group by col2 having count(1) > 1)

how to repeat each row twice

I have a requirement for a report and I would like my sql query to repeat each row twice.
Example :
**Table 1**
Id Name
1 Ab
2 Cd
3 Ef
I want to write a query which outputs the following :
1 Ab
1 Ab
2 Cd
2 Cd
3 Ef
3 Ef
Is there a way I can do it ?
I cannot think of anything except using union
Select Id, name from Table1 union select Id, name from Table1
You can use a union all. A union will not work, because it will eliminate duplicates. Another way is a cross join:
select id, name
from table1 t1 cross join
(select 1 as n union all select 2) n;
You can also use UNION ALL, put them under CTE (Common Table Expression) and Order By Id:
WITH CTE AS
(
SELECT Id, Name FROM Table_1
UNION ALL
SELECT Id, Name FROM Table_1
)
SELECT Id, Name
FROM CTE
ORDER BY Id;
As this will reorder them and stacked them as duplicates
Solution will be like this:
select Id, name from Table1
union all
select Id, name from Table1

Show all rows that have certain columns duplicated

suppose I have following sql table
objid firstname lastname active
1 test test 0
2 test test 1
3 test1 test1 1
4 test2 test2 0
5 test2 test2 0
6 test3 test3 1
Now, the result I am interested in is as follows:
objid firstname lastname active
1 test test 0
2 test test 1
4 test2 test2 0
5 test2 test2 0
How can I achieve this?
I have tried the following query,
select firstname,lastname from table
group by firstname,lastname
having count(*) > 1
But this query gives results like
firstname lastname
test test
test2 test2
You've found your duplicated records but you're interested in getting all the information attached to them. You need to join your duplicates to your main table to get that information.
select *
from my_table a
join ( select firstname, lastname
from my_table
group by firstname, lastname
having count(*) > 1 ) b
on a.firstname = b.firstname
and a.lastname = b.lastname
This is the same as an inner join and means that for every record in your sub-query, that found the duplicate records you find everything from your main table that has the same firstseen and lastseen combination.
You can also do this with in, though you should test the difference:
select *
from my_table a
where ( firstname, lastname ) in
( select firstname, lastname
from my_table
group by firstname, lastname
having count(*) > 1 )
Further Reading:
A visual representation of joins from Coding Horror
Join explanation from Wikipedia
SELECT DISTINCT t1.*
FROM myTable AS t1
INNER JOIN myTable AS t2
ON t1.firstname = t2.firstname
AND t1.lastname = t2.lastname
AND t1.objid <> t2.objid
This will output every row which has a duplicate, basing on firstname and lastname.
Here's a little more legible way to do Ben's first answer:
WITH duplicates AS (
select firstname, lastname
from my_table
group by firstname, lastname
having count(*) > 1
)
SELECT a.*
FROM my_table a
JOIN duplicates b ON (a.firstname = b.firstname and a.lastname = b.lastname)
SELECT user_name,email_ID
FROM User_Master WHERE
email_ID
in (SELECT email_ID
FROM User_Master GROUP BY
email_ID HAVING COUNT(*)>1)
nice option get all duplicated value from tables
select * from Employee where Name in (select Name from Employee group by Name having COUNT(*)>1)
This is the easiest way:
SELECT * FROM yourtable a WHERE EXISTS (SELECT * FROM yourtable b WHERE a.firstname = b.firstname AND a.secondname = b.secondname AND a.objid <> b.objid)
If you want to print all duplicate IDs from the table:
select * from table where id in (select id from table group By id having count(id)>1)
I'm surprised that there is no answer using Window function. I just came across this use case and this helped me.
select t.objid, t.firstname, t.lastname, t.active
from
(
select t.*, count(*) over (partition by firstname, lastname) as cnt
from my_table t
) t
where t.cnt > 1;
Fiddle - https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=c0cc3b679df63c4d7d632cbb83a9ef13
The format goes like
select
tbl.relevantColumns
from
(
select t.*, count(*) over (partition by key_columns) as cnt
from desiredTable t
) as tbl
where tbl.cnt > 1;
This format selects whatever columns you require from the table (sometimes all columns) where the count > 1 for the key_columns being used to identify the duplicate rows. key_columns can be any number of columns.
This answer may not be great one, but I think it is simple to understand.
SELECT * FROM table1 WHERE (firstname, lastname) IN ( SELECT firstname, lastname FROM table1 GROUP BY firstname, lastname having count() > 1);
This Query returns dupliacates
SELECT * FROM (
SELECT a.*
FROM table a
WHERE (`firstname`,`lastname`) IN (
SELECT `firstname`,`lastname` FROM table
GROUP BY `firstname`,`lastname` HAVING COUNT(*)>1
)
)z WHERE z.`objid` NOT IN (
SELECT MIN(`objid`) FROM table
GROUP BY `firstname`,`lastname` HAVING COUNT(*)>1
)
Please try
WITH cteTemp AS (
SELECT EmployeeID, JoinDT,
row_number() OVER(PARTITION BY EmployeeID, JoinDT ORDER BY EmployeeID) AS [RowFound]
FROM dbo.Employee
)
SELECT * FROM cteTemp WHERE [RowFound] > 1 ORDER BY JoinDT

how to write below sql query with all mentioned conditions?

I am using java/oracle. i have below issue.
SELECT
DISTINCT id_one,
status
FROM
sometable
WHERE
id_two IN (
SELECT
DISTINCT id_two
FROM
othertable
)
AND id_one IN (1946,1948,1949)
i have above query to fetch data from one table. inner query's data from other table.
now i need add one where condition to inner query.
othertable has one more field called name.
these are the ids that i mentioned: 1946,1948,1949. here each id will have names as below: name1, name2, name3
name1, name2, name3 are passed from java application.
finally the query that i need as follows.
SELECT
DISTINCT id_one,
status
FROM
sometable
WHERE
id_two IN (
SELECT
DISTINCT id_two
FROM
othertable other where other.name in('name1','name2','name3')
)
AND id_one IN (1946,1948,1949)
my questions is: for 1946 id name1 should be considered and for 1948 id name2 should be considered
*and for 1949 id name3 should be considered as criteria.* i mean query should not consider all 3 names for every id.
how can i achieve it?
This can also be done like in the following way:
select distinct s.id_one, s.status
from sometable s join othertable o on (s.id_two = o.id_two)
where (s.id_one = 1946 and o.name = 'name1')
OR (s.id_one = 1948 and o.name = 'name2')
OR (s.id_one = 1949 and o.name = 'name3');
From doc: http://docs.oracle.com/cd/B19306_01/server.102/b14200/conditions013.htm
SELECT DISTINCT id_one, status
FROM sometable
WHERE
id_two IN (
SELECT DISTINCT id_two
FROM othertable other
where ( other.name, id_one ) in (
select 'name1',1946 from dual union all
select 'name2',1948 from dual union all
select 'name3',1949 from dual )
)