SQL Group By Question - sql

I have a table that has the below columns.
I need to find out those people that has More than 2 ApplicantRowid with same jobcategoryrowid and AssessmentTest should have atleast one row NULL with Different Appstatusrowid's.
The result should look exeactly like the below table.
Rowid ApplicantRowid JobCategoryRowid AssessmentTestRowid AppstatusRowid
10770598 6952346 157 3 5
11619676 6952346 157 NULL 6

select t.*
from
(
select ApplicantRowid, JobCategoryRowid
from tbl
group by ApplicantRowid, JobCategoryRowid
having count(AssessmentTestRowid) < count(*)
and count(distinct AppstatusRowid) > 1
) x
inner join t on t.ApplicantRowid = x.ApplicantRowid
and t.JobCategoryRowid = x.JobCategoryRowid
COUNT does not include NULLs, so count(AssessmentTestRowid) < count(*) ensures there is at least a NULL
count(distinct AppstatusRowid) > 1 ensure there are different AppstatusRowids

Related

SQL COUNT with condition and without - using JOIN

My goal is something like following table:
Key | Count since date X | Count total
1 | 4 | 28
With two simple selects I could gain this values: (the key of the table consists of 3 columns [t$ncmp, t$trav, t$seqn])
1. SELECT COUNT(*) FROM db.table WHERE t$date >= sysdate-2 GROUP BY t$ncmp, t$trav, t$seqn
2. SELECT COUNT(*) FROM db.table GROUP BY t$ncmp, t$trav, t$seqn
How can I join these statements?
What I tried:
SELECT n.t$trav, COUNT(n.t$trav), m.total FROM db.table n
LEFT JOIN (SELECT t$ncmp, t$trav, t$seqn, COUNT(*) as total FROM db.table
GROUP BY t$ncmp, t$trav, t$seqn) m
ON (n.t$ncmp = m.t$ncmp AND n.t$trav = m.t$trav AND n.t$seqn = m.t$seqn)
WHERE n.t$date >= sysdate-2
GROUP BY n.t$ncmp, n.t$trav, n.t$seqn
I tried different variantes, but always got errors like 'group by is missing' or 'unknown qualifier'.
Now this at least executes, but total is always 2.
T$TRAV COUNT(N.T$TRAV) TOTAL
4 2 2
29 3 2
51 1 2
62 2 2
16 1 2
....
If it matter, I will run this as an OPENQUERY from MSSQLSERVER to Oracle-DB.
I'd try
GROUP BY n.t$trav, m.total
You typically GROUP BY the same columns as you SELECT - except those who are arguments to set functions.
My goal is something like following table:
If so, you seem to want conditional aggregation:
select key, count(*) as total,
sum(case when datecol >= date 'xxxx-xx-xx' then 1 else 0 end) as total_since_x
from t
group by key;
I'm not sure how this relates to your sample queries. I simply don't see the relationship between that code and your question.

How to use multiple counts in where clause to compare data of a table in sql?

I want to compare data of a table with its other records. The count of rows with a specific condition has to match the count of rows without the where clause but on the same grouping.
Below is the table
-------------
id name time status
1 John 10 C
2 Alex 10 R
3 Dan 10 C
4 Tim 11 C
5 Tom 11 C
Output should be time = 11 as the count for grouping on time column is different when a where clause is added on status = 'C'
SELECT q1.time
FROM (SELECT time,
Count(id)
FROM table
GROUP BY time) AS q1
INNER JOIN (SELECT time,
Count(id)
FROM table
WHERE status = 'C'
GROUP BY time) AS q2
ON q1.time = q2.time
WHERE q1.count = q2.count
This is giving the desired output but is there a better and efficient way to get the desired result?
Are you looking for this :
select t.*
from table t
where not exists (select 1 from table t1 where t1.time = t.time and t1.status <> 'C');
However you can do :
select time
from table t
group by time
having sum (case when status <> 'c' then 1 else 0 end ) = 0;
If you want the times where the rows all satisfy the where clause, then in Postgres, you can express this as:
select time
from t
group by time
having count(*) = count(*) filter (where status = 'C');

SQL Select from 1 table rows with 2 specific column value that are not equal

I have a table
id number name update_date
1 123 asd 08.05.18
2 412 ddd 08.05.18
3 123 dsa 14.05.18
4 125 dsa 05.05.18
Whole table consist from that rows like that. I need to select row 1 and 3 because I need different update_dates but same number. How to do that? I need to see the changes from specific Number between 2 update dates 08.05.18 and 14.05.18. I have more update dates in my table.
I tried:
SELECT *
FROM legal_entity_history a
JOIN legal_entity_history b ON a.BIN = b.BIN
WHERE ( a.update_date <> b.update_date AND
a.update_date = "08.05.18" AND
b.update_date = "14.05.18" )
A relatively simple method is:
select leh.*
from legal_entity_history leh
where exists (select 1
from legal_entity_history leh2
where leh2.number = leh.number and leh2.update_date <> leh.update_date
);
For performance, you want an index on legal_entity_history(number, update_date).
TRY THIS: Assuming that same number may not appear more than once under same update_date, so, you can achieve that using GROUP BY with HAVING as below
SELECT t.*
FROM test t
INNER JOIN (SELECT number
FROM test
GROUP BY number
HAVING COUNT(DISTINCT update_date) > 1) t1 ON t1.number = t.number
OUTPUT:
id number name update_date
1 123 asd 08.05.18
3 123 dsa 14.05.18

SQL aggregate rows with same id , specific value in secondary column

I'm looking to filter out rows in the database (PostgreSQL) if one of the values in the status column occurs. The idea is to sum the amount column if the unique reference only has a status equals to 1. The query should not SELECT the reference at all if it has also a status of 2 or any other status for that matter. status refers to the state of the transaction.
Current data table:
reference | amount | status
1 100 1
2 120 1
2 -120 2
3 200 1
3 -200 2
4 450 1
Result:
amount | status
550 1
I've simplified the data example but I think it gives a good idea of what I'm looking for.
I'm unsuccessful in selecting only references that only have status 1.
I've tried sub-queries, using the HAVING clause and other methods without success.
Thanks
Here's a way using not exists to sum all rows where the status is 1 and other rows with the same reference and a non 1 status do not exist.
select sum(amount) from mytable t1
where status = 1
and not exists (
select 1 from mytable t2
where t2.reference = t1.reference
and t2.status <> 1
)
SELECT SUM(amount)
FROM table
WHERE reference NOT IN (
SELECT reference
FROM table
WHERE status<>1
)
The subquery SELECTs all references that must be excluded, then the main query sums everything except them
select sum (amount) as amount
from (
select sum(amount) as amount
from t
group by reference
having not bool_or(status <> 1)
) s;
amount
--------
550
You could use windowed functions to count occurences of status different than 1 per each group:
SELECT SUM(amount) AS amount
FROM (SELECT *,COUNT(*) FILTER(WHERE status<>1) OVER(PARTITION BY reference) cnt
FROM tc) AS sub
WHERE cnt = 0;
Rextester Demo

How to update every rows which has a number greater than or equal to the joining table?

Here is an example of the tables I am joining together (note: the tables have the exact same schema but are in different databases, I am trying to combine them):
Database 1 Table
UniqID UniqID2 Number
100 150 1
100 151 2
Database 2 Table
UniqID UniqID2 Number
100 152 2
100 153 3
I am trying to merge Table2 into Table1 and I'm joining on Table1.UniqID = Table2.UniqID. I don't want any overlapping values in the Number column, this is what I want the result to look like:
Table 1
UniqID UniqID2 Number
100 150 1
100 151 2
100 152 3
100 153 4
This is the query I have so far, but it only updates the row in Table 2 where the Number = 2 and doesn't increment the Number = 3 row. How can I adjust my query to do so?
UPDATE db2
Set db2.Number = db2.Number +
(SELECT MAX(Number) FROM [Database 1]..db1 WHERE UniqID = db2.UniqID)
FROM [Database 2]..table db2
INNER JOIN [Database 1]..Table db1
ON db1.UniqID = db2.UniqID
AND db1.Number = db2.Number
And this is what my Database 2 Table results look like right now:
Database 2 Table
UniqID UniqID2 Number
100 152 3
100 153 3
Basically, the only difference is that I want the Number = 3 to be Number = 4 in the second column.
I think you want a union all query and insert:
insert into table1(UniqID, UniqID2, Number)
select t2.UniqID, t2.UniqID2,
(x.maxn + row_number() over (order by (select null) ))
from table2 t2 cross join
(select max(number) as maxn from table1) x;
A different appraoch could be
UPDATE t2
SET t2.Number = t1.T1Number + 1
FROM table2 t2
INNER JOIN (SELECT uniqid, uniqid2, number as T1Number from Table1
union
SELECT uniqid, uniqid2, number as T1Number from Table2
) t1
ON t1.uniqid = t2.uniqid and t1.UniqID2 = t2.UniqID2-1
one more approach which works in SQL 2012..
Demo here
;With cte
as
(select *
from
#t
union all
select *
from #t1
)
select uniqid,uniqid2,
case when lag(number) over (order by uniqid,uniqid2) is null then number
when lead(number) over (order by uniqid,uniqid2) is null
then number+1 else lead(number) over (order by uniqid,uniqid2) end as nextnumber
from cte