SQL Sub query and case statment - sql

I got unique ID's from POS table by using the below code where now I need to get the address information next to it comparing them with customer master table.
select
subqueries.id
from
(
select (cust_key) as id from dbo.pos
union
select (disti_key) as id from dbo.pos
union
select (reseller_key) as id from dbo.pos
)subqueries

I assumed that the customer master table has a primary key column id and let it have the name customers
select subqueries.id, c.adress
from (select (cust_key) as id from pos
union
select (disti_key) as id from pos
union
select (reseller_key) as id from pos
) subqueries
join customers c on subqueries.id = c.id

Related

How to use array in a sql join and check if all of the array elements satisfy a condition?

I have two tables, activity and contacts in postgresql.
An activity can have multiple contacts in array form, like this
contact Id = {23,54,34}.
I want to delete a activity only if all the contact Ids of that activity are deleted in contacts table and keep the activity if at least one one contact id is still not deleted.
Deleted At is column in contacts table to check for deleted contacts. I don't want to use NOT IN.
Activity table
id contact Id
-------------------
16 {60,61,23}
15 {}
5 {59}
6 {}
You can use simple EXISTS predicate testing contacts table with activity.contacts array:
create table activity (
id int primary key,
contacts int[]
)
create table contacts (
id int primary key,
name varchar(10),
deleted boolean
)
insert into activity
select 16 as id, '{1,2,3}'::int[] as contacts union all
select 15, null union all
select 5, '{4}' union all
select 6, '{6, 5}'
insert into contacts
select 1 as id, 'q' as name, false as deleted union all
select 2, 'w', false union all
select 3, 'e', true union all
select 4, 'r', false union all
select 5, 't', true union all
select 6, 'y', true
delete
from activity a
where not exists (
select null
from contacts c
where not(c.deleted)
and c.id = any(a.contacts)
)
2 rows affected
db<>fiddle here
Use UNNEST to convert the nested-array to rows, then do an anti-join to look for broken references:
(An anti-join is when you perform a x LEFT OUTER JOIN y with a WHERE y.KeyColumn IS NULL - this gives you the opposite of an INNER JOIN with the same join criteria).
WITH unnested AS (
SELECT
Id AS ActivityId,
UNNEST( ContactId ) AS ContactIdFromArray
FROM
crmActivity
)
SELECT
u.ActivityId,
u.ContactIdFromArray AS Missing_ContactId_in_Activity
FROM
unnested AS u
LEFT OUTER JOIN contacts AS c ON
c.ContactId = u.ContactIdFromArray
WHERE
c.ContactId IS NULL
ORDER BY
u.ActivityId
I want to delete a activity only if all the contact Ids of that activity are deleted in contacts table and keep the activity if at least one one contact id is still not deleted.
This can be done with a DELETE FROM using WHERE crmActivity.Id IN with a CTE that generates the correct set of bad crmActivity.Id values, via a GROUP BY with the above query:
WITH unnested AS (
SELECT
Id AS ActivityId,
UNNEST( ContactId ) AS ContactIdFK
FROM
crmActivity
)
WITH brokenContacts AS (
SELECT
u.ActivityId,
u.ContactIdFK,
c.ContactId AS ContactIdPK
FROM
unnested AS u
LEFT OUTER JOIN contacts AS c ON
c.ContactId = u.ContactIdFromArray
)
WITH counts AS (
SELECT
ActivityId,
COUNT(*) AS ContactIdCount,
COUNT( CASE WHEN ContactIdPK IS NULL THEN 1 END ) AS BadContactIdCount
FROM
brokenContacts
GROUP BY
ActivityId
)
WITH badActivityIds AS (
SELECT
ActivityId
FROM
counts
WHERE
BadContactIdCount = ContactIdCount
AND
ContactIdCount > 0
)
DELETE FROM
crmActivity
WHERE
ActivityId IN ( SELECT ActivityId FROM badActivityIds );

Display the names of each employees who works in both ‘IT’ and ‘SE’

Emp(sid(pk) : integer, sname: varchar(255))
Dep(sid(fk) : integer, dep : varchar(255))
SQL:How I find the names of each employees who works in both ‘IT’ and ‘SE’?
To observe a query that Joins two tables together and get common values depend on a common column Ex: id, using INNTER JOIN will help you on that
The INNER JOIN keyword selects records that have matching values in both tables.
Solution
SELECT Emp.sid, Emp.sname FROM Emp
INNER JOIN
(SELECT sid FROM Dep WHERE dep='IT'
INTERSECT
SELECT sid FROM Dep WHERE dep='SE') as A
ON Emp.sid = A.sid
References
SQL INNER JOIN
The way I understand it, the data situation is as below. emp with sid and sname, and dep, with sid - the foreign key to emp and dep, this time not as a table, but a column containing the department's abbreviation. And the combination, in the dep table, of sid and dep, is unique.
If that is the constellation, then join the two tables using sid, filter by: dep in the set:('IT' , 'SE'); Then, put the two columns from emp into the the column list, and GROUP BY them, and finally, apply the grouping filter HAVING COUNT(*) = 2 to just get the group that has two entries when filtered by the two departments.
WITH
emp(sid, sname) AS (
SELECT 42,'Arthur'
UNION ALL SELECT 43,'Ford'
UNION ALL SELECT 44,'Zaphod'
)
,
dep(sid, dep) AS (
SELECT 42,'IT'
UNION ALL SELECT 42,'SE'
UNION ALL SELECT 42,'AC'
UNION ALL SELECT 43,'IT'
UNION ALL SELECT 43,'AC'
UNION ALL SELECT 44,'SE'
UNION ALL SELECT 44,'SA'
)
SELECT
emp.sid
, emp.sname
FROM emp JOIN dep USING(sid)
WHERE dep.dep IN ('IT','SE')
GROUP BY
emp.sid
, emp.sname
HAVING COUNT(*) = 2;
-- out sid|sname
-- out 42|Arthur

SQL Query – records within the SQL Select statement, but NOT in the table being queried

I have a large list of CustIDs that I need to query on to find if they are within the CUSTOMER table; I want the result to tell me which CustIDs ARE on the table and which CustIDs are NOT on the table.
I provided a short list below to give an idea of what I need to do.
Oracle database
Table: Customer
Primary Key: CustID
Scenario:
Customer table only has the following (2) CustID: ‘12345’, ‘56789’
Sql:
Select * from CUSTOMERS where CUSTID in (‘12345’, ‘56789’, ‘01234’);
I want the result to tell me that both ‘12345’ and ‘56789’ are in the table, AND that ‘01234’ is NOT.
select
v.CustID,
exists (select * from Customer where Customer.CustID = v.CustID)
from (values (12345), (56789), (01234)) v (CustID);
Results:
custid exists
12345 true
56789 true
1234 false
You need a left join or subquery for this. The precise syntax varies by database. Typical syntax is:
select i.custid,
(case when c.custid is not null then 1 else 0 end) as exists_flag
from (select '12345' as custid union all
select '56789' union all
select '01234'
) ci left join
customers c
on c.cust = i.custid;

SQL derived table. Easy SQL

Hi i get the error 'Every derived table must have its own alias' what can i do about it??
My question is :
Show team ID and names from teams from Germany who have never played in UEFA Champions league
UEFA Champions league = 1
Cid= Competions ID
Tid = Team ID
SELECT teams.TID, teams.name from(
SELECT Tid1 FROM(
(SELECT tid1,cid FROM matches
WHERE tid1 IN (SELECT tid FROM teams WHERE country='Germany')
UNION
SELECT tid2,cid FROM matches
WHERE tid2 IN (SELECT tid FROM teams WHERE country='Germany'))
)WHERE cid <> (SELECT cid FROM competitions WHERE cid='1'))
INNER JOIN matches ON tid1=team.tid;
I have tried looking at others derived soulutions but i cant get to work with mine...
It looks like its asking for you to give alias to the tables you have created within the query. Try this.
EFA Champions league = 1
Cid= Competions ID
Tid = Team ID
SELECT teams.TID, teams.name from(
SELECT Tid1 FROM(
(SELECT tid1,cid FROM matches
WHERE tid1 IN (SELECT tid FROM teams WHERE country='Germany')
UNION
SELECT tid2,cid FROM matches
WHERE tid2 IN (SELECT tid FROM teams WHERE country='Germany'))ALIAS1
)WHERE cid <> (SELECT cid FROM competitions WHERE cid='1')) ALIAS2
INNER JOIN matches ON tid1=team.tid;

How to combine three SELECT statements with very tricky requirements

I have a SQL query with three SELECT statements. A picture of the data tables generated by these three select statements is located at www.britestudent.com/pub/1.png. Each of the three data tables have identical columns. I want to combine these three tables into one table such that:
(1) All rows in top table (Table1) are always included.
(2) Rows in the middle table (Table2) are included only when the values in column1 (UserName) and column4 (CourseName) do not match with any row from Table1. Both columns need to match for the row in Table2 to not be included.
(3) Rows in the bottom table (Table3) are included only when the value in column4 (CourseName) is not already in any row of the results from combining Table1 and Table2.
I have had success in implementing (1) and (2) with an SQL query like this:
SELECT DISTINCT
UserName AS UserName,
MAX(AmountUsed) AS AmountUsed,
MAX(AnsweredCorrectly) AS AnsweredCorrectly,
CourseName,
MAX(course_code) AS course_code,
MAX(NoOfQuestionsInCourse) AS NoOfQuestionsInCourse,
MAX(NoOfQuestionSetsInCourse) AS NoOfQuestionSetsInCourse
FROM
( "SELECT statement 1" UNION "SELECT statement 2" ) dt_derivedTable_1
GROUP BY CourseName, UserName
Where "SELECT statement 1" is the query that generates Table1 and "SELECT statement 2" is the query that generates Table2. A picture of the data table generated by this query is located at www.britestudent.com/pub/2.png. I can get away with using the MAX() function because values in the AmountUsed and AnsweredCorrectly columns in Table1 will always be larger than those in Table2 (and they are identical in the last three columns of both tables).
What I fail at is implementing (3). Any suggestions on how to do this will be appreciated. It is tricky because the UserName values in Table3 are null, and because the CourseName values in the combined Table1 and Table2 results are not unique (but they are unique in Table3).
After implementing (3), the final table should look like the table in picture 2.png with the addition of the last row from Table3 (the row with the CourseName value starting with "4. Klasse..."
I have tried to implement (3) using another derived table using SELECT, MAX() and UNION, but I could not get it to work. Below is my full SQL query with the lines from this failed attempt to implement (3) commented out.
Cheers,
Frederick
PS--I am new to this forum (and new to SQL as well), but I have had more of my previous problems answered by reading other people's posts on this forum than from reading any other forum or Web site. This forum is a great resources.
-- SELECT DISTINCT MAX(UserName), MAX(AmountUsed) AS AmountUsed, MAX(AnsweredCorrectly) AS AnsweredCorrectly, CourseName, MAX(course_code) AS course_code, MAX(NoOfQuestionsInCourse) AS NoOfQuestionsInCourse, MAX(NoOfQuestionSetsInCourse) AS NoOfQuestionSetsInCourse
-- FROM (
SELECT DISTINCT UserName AS UserName, MAX(AmountUsed) AS AmountUsed, MAX(AnsweredCorrectly) AS AnsweredCorrectly, CourseName, MAX(course_code) AS course_code, MAX(NoOfQuestionsInCourse) AS NoOfQuestionsInCourse, MAX(NoOfQuestionSetsInCourse) AS NoOfQuestionSetsInCourse
FROM (
-- Table 1 - All UserAccount/Course combinations that have had quizzez.
SELECT DISTINCT dbo.win_user.user_name AS UserName,
cast(dbo.GetAmountUsed(dbo.session_header.win_user_id, dbo.course.course_id, dbo.course.no_of_questionsets_in_course) as nvarchar(10)) AS AmountUsed,
Isnull(cast(dbo.GetAnswerCorrectly(dbo.session_header.win_user_id, dbo.course.course_id, dbo.question_set.no_of_questions) as nvarchar(10)),0) AS AnsweredCorrectly,
dbo.course.course_name AS CourseName,
dbo.course.course_code,
dbo.course.no_of_questions_in_course AS NoOfQuestionsInCourse,
dbo.course.no_of_questionsets_in_course AS NoOfQuestionSetsInCourse
FROM dbo.session_detail
INNER JOIN dbo.session_header ON dbo.session_detail.session_header_id = dbo.session_header.session_header_id
INNER JOIN dbo.win_user ON dbo.session_header.win_user_id = dbo.win_user.win_user_id
INNER JOIN dbo.win_user_course ON dbo.win_user_course.win_user_id = dbo.win_user.win_user_id
INNER JOIN dbo.question_set ON dbo.session_header.question_set_id = dbo.question_set.question_set_id
RIGHT OUTER JOIN dbo.course ON dbo.win_user_course.course_id = dbo.course.course_id
WHERE (dbo.session_detail.no_of_attempts = 1 OR dbo.session_detail.no_of_attempts IS NULL)
AND (dbo.session_detail.is_correct = 1 OR dbo.session_detail.is_correct IS NULL)
AND (dbo.win_user_course.is_active = 'True')
GROUP BY dbo.win_user.user_name, dbo.course.course_name, dbo.question_set.no_of_questions, dbo.course.no_of_questions_in_course,
dbo.course.no_of_questionsets_in_course, dbo.session_header.win_user_id, dbo.course.course_id, dbo.course.course_code
UNION ALL
-- Table 2 - All UserAccount/Course combinations that do or do not have quizzes but where the Course is selected for quizzes for that User Account.
SELECT dbo.win_user.user_name AS UserName,
-1 AS AmountUsed,
-1 AS AnsweredCorrectly,
dbo.course.course_name AS CourseName,
dbo.course.course_code,
dbo.course.no_of_questions_in_course AS NoOfQuestionsInCourse,
dbo.course.no_of_questionsets_in_course AS NoOfQuestionSetsInCourse
FROM dbo.win_user_course
INNER JOIN dbo.win_user ON dbo.win_user_course.win_user_id = dbo.win_user.win_user_id
RIGHT OUTER JOIN dbo.course ON dbo.win_user_course.course_id = dbo.course.course_id
WHERE (dbo.win_user_course.is_active = 'True')
GROUP BY dbo.win_user.user_name, dbo.course.course_name, dbo.course.no_of_questions_in_course,
dbo.course.no_of_questionsets_in_course, dbo.course.course_id, dbo.course.course_code
) dt_derivedTable_1
GROUP BY CourseName, UserName
-- UNION ALL
-- Table 3 - All Courses.
-- SELECT DISTINCT null AS UserName,
-- -2 AS AmountUsed,
-- -2 AS AnsweredCorrectly,
-- dbo.course.course_name AS CourseName,
-- dbo.course.course_code,
-- dbo.course.no_of_questions_in_course AS NoOfQuestionsInCourse,
-- dbo.course.no_of_questionsets_in_course AS NoOfQuestionSetsInCourse
-- FROM dbo.course
-- WHERE is_active = 'True'
-- ) dt_derivedTable_2
-- GROUP BY CourseName
-- ORDER BY CourseName
With such filtering requirements (depending on the rows of prior queries), I recommend a table variable.
DECLARE #MyTable TABLE
(
ID int PRIMARY KEY,
Name varchar(50),
QueryNumber int
)
INSERT INTO #MyTable (ID, Name, QueryNumber)
SELECT CustomerID, CustomerName, 1
FROM Customer
WHERE Name = "Bob"
INSERT INTO #MyTable (ID, Name, QueryNumber)
SELECT CustomerID, CustomerName, 2
FROM Customer
WHERE Name = "Joe" and CustomerID not in (SELECT ID FROM #MyTable)
INSERT INTO #MyTable (ID, Name, QueryNumber)
SELECT CustomerID, CustomerName, 3
FROM Customer
WHERE CustomerID not in (SELECT ID FROM #MyTable)
SELECT *
FROM #MyTable
Here is an Oracle flavored solution:
Select
*
from table1
UNION
select
*
from table2
where not exists(
select 'x'
from table1
where
table2.username = table1.username
and table2.coursename = table1.coursename
)
UNION
select
*
from table3
where
coursename not in (
Select
coursename
from table1
UNION /* the union operator implies distinct, so
there will be no duplicates */
select
coursename
from table2
where not exists(
select 'x'
from table1
where
table2.username = table1.username
and table2.coursename = table1.coursename
)
)