Merge multiple queries excluding common results - tsql

Data :
--Table 1 :
Id ZoneName
----------- --------
20011 Name1
10027 Name1
20011 Name1
20011 Name1
20011 Name1
20074 Name1
20011 Name2
20011 Name2
10059 Name3
20011 Name2
Query :
Select Top 2 [Id] From Table1 -- First Query
WHERE ZoneName = 'Name1'
UNION
SELECT Top 1 [Id] from Table1 -- Second Query
WHERE ZoneName = 'Name1'
UNION
SELECT Top 1 [Id] from Table1 -- Third Query
WHERE ZoneName = 'Name1'
Result :
Id
-----
20011
Expected Result :
20011
10027
20074
From the above query I need 3 results from each query that do NOT overlap each other, in this case the expected result should contain the top 2 for query 1 i.e. 20011 and 10027 and for the next top 1 it should exclude those 2 results and return 20074 for query 2.
Note : I have used a single WHERE condition for this example, however in the actual query each of the query has different Where conditions, and could end up having same / different result from the query above itself.

As far as I know If you are searching to query distinct Id's for a particular ZoneName then this may work out
SELECT DISTINCT ID
FROM TABLE1
WHERE ZoneName="Name1"

Related

String aggregation in postgresql table using psycopg2

I have following table in Postgresql 11.0.
id code name1 name2
1 XXX abc sdf
1 XXX def null
2 ZZZ zut null
3 YYY gtj bzu
3 YYY null nuz
I would like to aggregate the values in name1 and name2 column for each id (in python). The below query runs perfectly in pgadmin but gives error through python script.
try:
cursor.execute("""
UPDATE tbl t1
SET name1 = sub_q.name1,
name2 = sub_q.name2
FROM
(
SELECT id, code, string_agg(name1, ' ; ') as name1, string_agg(name2, ' ; ') as name2
FROM tbl as t2
GROUP BY t2.id, t2.code
) AS sub_q
WHERE sub_q.id= t1.id
;
)
""")
except:
print ("The table cannot be created")
The expected output is:
id code name1 name2
1 XXX abc; def sdf
2 ZZZ zut null
3 YYY gtj bzu; nuz

How to get the gap in result from union all in tables?

select id,name from t1
id name
1 A
2 B
select id,name,sal from t2
id name sal
1 C 1000
2 D 2000
select id,name,Null as sal from t1
UNION ALL
select id,name,sal from t2
id name sal
1 A
2 B
1 C 1000
2 D 2000
But I need like this
id name sal
1 A
2 B
1 C 1000
2 D 2000
There should be some gap required between two results
This is more like a reporting type of query since you are asking about formatting of the data layout rather than the content itself. You can somehow tweak the result using:
select id, name, sal
from (
select 1 as section, id, name, null as sal from t1
UNION ALL
select 2, null, null, null
UNION ALL
select 3, id, name, sal from t2
) x
order by section
However, it's worth to point out that formatting is better done in the UI rather than at the database level. At the UI you have access to fonts, colors, borders, bold, italics, underline, etc.

SQL Query required where we should not used the group by and data count based on dep_id

Need your help in getting the SQL Query.
1. I have one table which is having following columns
Name Null? Type
------------ -------- ------------
EMP_ID NOT NULL NUMBER(2)
DEP_ID NUMBER(2)
SALARY NUMBER(14,3)
NAME1 VARCHAR2(50)
NAME2 VARCHAR2(50)
JOINING_DATE DATE
Now I want the result - COUNT(1) based on DEP_ID without using GROUP BY .
EXAMPLE :
select DEP_ID,COUNT(1) from unipartemp group by DEP_ID;
DEP_ID COUNT(1)
1 2
2 2
3 1
What is the Query where we should get the same result but we should not use group by ...
Please suggest .
I am assuming that the result u r looking for is the count of the distinct dept_id. Try using the distinct(dept_id) to get the result.

Postgres how to maintain order of rows using CTEs

I have 2 tables
students:
id | name | age
1 abc 20
2 xyz 21
scores:
id | studentid | marks
1 1 20
2 2 22
3 2 20
4 1 22
5 1 20
where studentid is foreign key to students table
When a do
select studentid
from scores
where marks=20;
I get the following result
1, 2, 1
But if want the name of the student name and when I do a join using
select t1.name
from students t1
inner join scores t2 on t1.id = t2.studentid
where t2.marks=20;
I get xyz,abc,abc Though the ouput is correct is there any way I can maintain the order in which scores are listed in the scores table? I should get abc,xyz,abc as output. I tried using subquery as well
SELECT name
FROM students
WHERE ID IN ( select studentid from scores where marks=20) ;
but that also did not give me correct order. How can this be achieved using CTEs (common table expressions)? I tried the follownig cte but it did not work
with cte as(
select t2.id, t1.name
from students t1
inner join scores t2 on t1.id = t2.studentid
where t2.marks=20)
select name from cte order by id
You can order by a column not present in select list:
select t1.name
from students t1
inner join scores t2 on t1.id = t2.student_id
where t2.marks=20
order by t2.id;
name
------
abc
xyz
abc
(3 rows)

Update Count column in Postgresql

I have a single table laid out as such:
id | name | count
1 | John |
2 | Jim |
3 | John |
4 | Tim |
I need to fill out the count column such that the result is the number of times the specific name shows up in the column name.
The result should be:
id | name | count
1 | John | 2
2 | Jim | 1
3 | John | 2
4 | Tim | 1
I can get the count of occurrences of unique names easily using:
SELECT COUNT(name)
FROM table
GROUP BY name
But that doesn't fit into an UPDATE statement due to it returning multiple rows.
I can also get it narrowed down to a single row by doing this:
SELECT COUNT(name)
FROM table
WHERE name = 'John'
GROUP BY name
But that doesn't allow me to fill out the entire column, just the 'John' rows.
you can do that with a common table expression:
with counted as (
select name, count(*) as name_count
from the_table
group by name
)
update the_table
set "count" = c.name_count
from counted c
where c.name = the_table.name;
Another (slower) option would be to use a co-related sub-query:
update the_table
set "count" = (select count(*)
from the_table t2
where t2.name = the_table.name);
But in general it is a bad idea to store values that can easily be calculated on the fly:
select id,
name,
count(*) over (partition by name) as name_count
from the_table;
Another method : Using a derived table
UPDATE tb
SET count = t.count
FROM (
SELECT count(NAME)
,NAME
FROM tb
GROUP BY 2
) t
WHERE t.NAME = tb.NAME