Count number of not exist in child table - sql

Essentially what I'm trying to do is count the number of rows something doesn't exist in an audit/history table. I'd like the following query to return a count of one per detail. Currently it gives me one per row in the history table.
--Detail Table
ID DETAIL_GROUP
1 A
2 B
3 B
--Detail History Table
DETAIL_ID_FK VALUE1
1 NOT_MATCH
1 NOT_MATCH
2 MATCH
2 NOT_MATCH
3 MATCH
3 NOT_MATCH
SELECT D.DETAIL_GROUP, COUNT(*)
FROM DETAIL D
WHERE (NOT EXISTS(
SELECT NULL
FROM DETAIL_HISTORY HI
WHERE HI.D_ID_FK = D.ID
AND HI.VALUE1 = 'MATCH'))
GROUP BY D.DETAIL_GROUP;
I'd like to see the following result:
DETAIL_GROUP COUNT(*)
A 1
but I'm receiving the following result:
DETAIL_GROUP COUNT(*)
A 2
Thank you in advance for any assistance provided.

Assuming that your detail table is as follows:
D_ID VALUE1
1 MATCH
1 NOT_MATCH
2 MATCH
2 NOT_MATCH
3 MATCH
3 NOT_MATCH
The below query:
SELECT d.detail_group, count(*)
FROM detail d
JOIN detail_history dh ON dh.d_id = d.id
WHERE dh.value1 = 'MATCH'
GROUP BY d.detail_group
Would produce:
DETAIL_GROUP COUNT(*)
A 1
B 2
The above query creates the groups matching the ids and then goes into each group and restricts the items based on value1.

Related

Merge row values based on other column value

I'm trying to merge the values of two rows based on the value of another row in a different column. Below is my based table
Customer ID
Property ID
Bookings per customer
Cancellations per customer
A
1
0
1
B
2
10
1
C
3
100
1
C
4
100
1
D
5
20
1
Here is the SQL query I used
select customer_id, property_id, bookings_per_customer, cancellations_per_customer
from table
And this is what I want to see. Any ideas the query to get this would be? We use presto SQL
Thanks!
Customer ID
Property ID
Bookings per customer
Cancellations per customer
A
1
0
1
B
2
10
1
C
3 , 4
100
1
D
5
20
1
We can try:
SELECT
customer_id,
ARRAY_JOIN(ARRAY_AGG(property_id), ',') AS properties,
bookings_per_customer,
cancellations_per_customer
FROM yourTable
GROUP BY
customer_id,
bookings_per_customer,
cancellations_per_customer;

Find whether id matches and substitute using Case Hive query

I have a table called "Scan" customer transactions where an individual_id appears once for every different transaction and contains column like scan_id.
I have another table called ids which contains random individual_ids sampled from Scan Table
I would like to join ids with scan and get a single record of ids and scan_id if it matches certain values.
Suppose data is like below
Scan table
Ids scan_id
---- ------
1 100
1 111
1 1000
2 100
2 111
3 124
4 1000
4 111
Ids table
id
1
2
3
4
5
I want below output i.e if scan_id matches either 100 or 1000
Id MT
------ ------
1 1
2 1
3 0
4 1
I executed below query and got error
select MT, d.individual_id
from
(
select
CASE
when scan_id in (90069421,53971306,90068594,136739913,195308160) then 1
ELSE 0
END as MT
from scan cs join ids r
on cs.individual_id = r.individual_id
where
base_div_nbr =1
and
country_code ='US'
and
retail_channel_code=1
and visit_date between '2019-01-01' and '2019-12-31'
) as d
group by individual_id;
I would appreciate any suggestions or help with regard to this Hive query. If there is an efficient way of getting this job done. Let me know.
Use a group by:
select s.individual_id,
max(case when s.scan_id in (100, 1000) then 1 else 0 end) as mt
from scan s
group by s.individual_id;
The ids table doesn't seem to be needed for this query.

Create multiple rows based on 1 column

I currently have a table with a quantity in it.
ID Code Quantity
1 A 1
2 B 3
3 C 2
4 D 1
Is there anyway to write a sql statement that would get me
ID Code Quantity
1 A 1
2 B 1
2 B 1
2 B 1
3 C 1
3 C 1
4 D 1
I need to break out the quantity and have that many number of rows
Thanks
Here's one option using a numbers table to join to:
with numberstable as (
select 1 AS Number
union all
select Number + 1 from numberstable where Number<100
)
select t.id, t.code, 1
from yourtable t
join numberstable n on t.quantity >= n.number
order by t.id
Online Demo
Please note, depending on which database you are using, this may not be the correct approach to creating the numbers table. This works in most databases supporting common table expressions. But the key to the answer is the join and the on criteria.
One way would be to generate an array with X elements (where X is the quantity). So for rows
ID Code Quantity
1 A 1
2 B 3
3 C 2
you would get
ID Code Quantity ArrayVar
1 A 1 [1]
2 B 3 [1,2,3]
3 C 2 [2]
using a sequence function (e.g, in PrestoDB, sequence(start, stop) -> array(bigint))
Then, unnest the array, so for each ID, you get a X rows, and set the quantity to 1. Not sure what SQL distribution you're using, but this should work!
You can use connect by statement to cross join tables in order to get your desired output.
check my solution it works pretty robust.
select
"ID",
"Code",
1 QUANTITY
from Table1, table(cast(multiset
(select level from dual
connect by level <= Table1."Quantity") as sys.OdciNumberList));

Get duplicate on single column after distinct across multiple columns in SQL

I have a table that looks like this:
name | id
-----------
A 1
A 1
B 2
C 1
D 3
D 3
F 2
I want to return id's 1 and 2 because they are duplicate on names. I don't want to return 3, because it is distinct for D 3.
Basically, I'm thinking of doing a query to first get a distinct pairing, so the above reduces to
name | id
-----------
A 1
B 2
C 1
D 3
F 2
And then doing a duplicate find on the id column. However, I'm struggling to find the correct syntax to construct that query.
You should be able to get the result you want by using a GROUP BY along with a HAVING clause that counts the distinct names. The HAVING clause will filter for those ids that have more than one distinct name:
select id
from Table1
group by id
having count(distinct name) > 1
Here is a demo

SQL select Name entries for which a certain requirement is NEVER fulfilled

I need to select Name entries for which none of the rows fulfills a certain requirement. This is best described as an example- lets consider the following table:
Name Number ID
A 1 2
A 2 2
B 1 2
B 2 3
C 3 3
The requirement would be that Number=ID. For the name B this is never the case, so I would like to return the Name B.
Name Number ID
A 1 2
A 2 2 <---- fulfills requirement for A
B 1 2
B 2 3
C 3 3 <---- fulfills requirement for C
Is this possible in SQL?
You can use a NOT EXISTS clause
select * from Table1 t1
where not exists (select null
from Table1
where t1.Name = Name
and Number = Id)
If you just want the names which don't fulfill the requirement, just change the select to
select distinct t1.Name
see SqlFiddle with both versions.
Try this
Select Name
from table
where name not in (Select distinct name from table where number = id )