SQL query for 3 tables by tour - sql

tourid
tourname
1
PARIS
2
LANDON
3
MADRID
tour_detail_ID
tourid
custid
1
1
3
2
2
3
3
3
3
4
1
4
5
2
4
6
3
4
7
1
5
8
2
5
custid
custname
custPhoneNo
3
PETER
22332422
4
MARY
22332422
5
PAUL
22332422
enter image description here
How can I get all customers booked all tours?

If I understand what your data is and what your question is, this will involve finding out who has not scheduled all of the tours and then finding all customers who aren't in the previous list.
I'm not sure I like it, but something like this gets just Peter and Mary, since they are the only two who have scheduled all 3 tours:
SELECT c1.custid, c1.custName
FROM #customers c1
LEFT OUTER JOIN (
SELECT c2.custid
FROM #tours t
CROSS JOIN #customers c2
LEFT OUTER JOIN #tour_detail td ON td.tourid = t.tourid
AND td.custid = c2.custid
WHERE td.custid IS NULL
) noCustTour ON c1.custid = noCustTour.custid
WHERE noCustTour.custid IS NULL

Related

How to add a condition to count function in PostgreSQL

I have these tables Course, subscription,subscription_Course(A table that creates a relation between Course and subscription), and another with Student. I want to Select all the id_courses that have a subscription count higher than 1 but only want to count the subscriptions from different students. Example: If a Student Subscribes two times the same course I want to have a condition that enables the count function to not count more than one time in these cases
These are my tables:
Student:
idStudent(pk)
cc
nif
1
30348507
232928185
2
30338507
231428185
3
30438507
233528185
4
30323231
3232132
Subscription
idsubscription(pk)
Student(fk)
value_subscription
vouchercurso
date
1
1
100
null
2021-11-01
2
2
150
null
2021-12-11
3
3
160
null
2021-01-03
4
4
500
null
1996-11-07
5
1
900
null
2001-07-05
6
2
432
null
2021-05-09
Subscription_Course
idsubscription(PK/fk)
id_Course(pk/fk)
Grade
1
3
9
2
4
15
3
5
12
6
3
9
5
4
16
2
6
20
6
5
4
For example, when counting within my table Subscription_Course only the id_course:5 would have a count higher than 1 because 3 and 4 have a subscription from the same student.
I have this query for now:
Select id_Course
From Subscription_Course
Group by id_Course
Having Count (id_Course)>1
I don't know what to do to add this condition to the count.
seems like you need to join to Subscription and count unique Student id's:
select id_Course
from Subscription_Course sc
join Subscription s
on s.idsubscription = sc.idsubscription
group by id_Course
having Count(distinct Studentid)>1
You can join the Subscription_Course table with the Subscription table in order to access the id_Student column. Then just count the distinct id_Student values for each id_Course value.
SELECT
Subscription_Course.id_Course,
COUNT(DISTINCT Subscription.id_Student) AS student_count
FROM Subscription_Course
INNER JOIN Subscription
ON Subscription_Course.id_Subscription = Subscription.id_Subscription
GROUP BY Subscription_Course.id_Course
HAVING COUNT(DISTINCT Subscription.id_Student) > 1
ORDER BY student_count DESC;
With result:
id_course | student_count
-----------+---------------
3 | 2
4 | 2
5 | 2

SQL Server: how to get this result from this table (example inside)

I would like to ask you guys how would you do a query to show the data of this table:
week name total
==== ====== =====
1 jon 15.2
1 jon 10
1 susan 10
1 howard 9
1 ben 10
3 ben 30
3 susan 10
3 mary 10
5 jon 10
6 howard 12
7 tony 25.1
8 tony 7
8 howard 10
9 susan 6.2
9 howard 9
9 ben 10
11 howard 10
11 howard 10
like this:
week name total
==== ====== =====
1 ben 10
1 howard 9
1 jon 25.2
1 mary 0
1 susan 10
1 tony 0
3 ben 30
3 howard 0
3 jon 0
3 mary 10
3 susan 10
3 tony 0
5 ben 0
5 howard 0
5 jon 10
5 mary 0
5 susan 0
5 tony 0
6 ben 0
6 howard 12
6 jon 0
6 mary 0
6 susan 0
6 tony 0
7 ben 0
7 howard 0
7 jon 0
7 mary 0
7 susan 0
7 tony 25.1
8 ben 0
8 howard 10
8 jon 0
8 mary 0
8 susan 0
8 tony 7
9 ben 10
9 howard 9
9 jon 0
9 mary 0
9 susan 6.2
9 tony 0
11 ben 0
11 howard 20
11 jon 0
11 mary 0
11 susan 0
11 tony 0
I tried something like:
select t1.week_id ,
t2.name ,
sum(t1.total)
from xpto as t1 ,
xpto as t2
where t1.week_id = t2.week_id
group by t1.week_id, t2.name
order by t1.week_id, t2.name
But I'm failing to understand the "sum" part and I can't figure out why...
Any help would be very appreciated. Thanks in advance, and sorry for my english.
you might try something like the following:
select week = w.week ,
name = n.name ,
sum_total = coalesce( sum( d.total ) , 0 )
from ( select distinct week from my_table ) w
cross join ( select distinct name from my_table ) n
left join my_table d on d.week = w.week
and d.name = n.name
group by w.week ,
n.name
order by 1,2
The cross join of first two derived tables constructs their cartesian product: all week and all names from the table, regardless of whether or not a particular week/name combination exists.
We then take that, join it against the actual data rows and summarize it, using coalesce() to collapse any null results from the aggregate function sum() to 0.
As I understood you you want to show all weeks and all names across all table regardless whether they were entered for the week or not. To do so you will need to first build a list of all names and week, cross join them and then join them to the list of totals, like this:
;with names as (select distinct name from xpto),
weeks as (select distinct week from xpto),
totals as (select week, name, sum(total) as total
from xpto group by week, name)
select w.week, n.name, coalesce(total, 0) as total
from names n cross join weeks w
left join totals t on t.name=n.name and w.week = t.week
order by 1,2
SQL Fiddle
I've edited my answer because I now understand what you want to do a bit better.
I prefer doing things in several steps rather than trying to do several transformations of data with a single join or subquery. So I would approach this like this:
;
with Weeks as (
select distinct Week_id
from xpto
)
, Names as (
select distinct Name
from xpto
)
, Scores as (
select week_id
, name
, score = sum(t1.score)
from xpto t1
group by
t1.week_id
, t1.name
)
, WeeksAndNames as (
select week_id
, name
from Weeks
cross join Names
)
-- The final query!
select wan.week_id
, wan.name
, total = COALESCE(s.total,0)
from WeeksAndNames wan
left join Scores s
on wan.week_id = s.week_id
and wan.name = s.name
order by
wan.week_id
, wan.name
Lengthy, I'll grant you, and you can probably condense it. But this shows each step you need to go through to transform your data into the list you want.

SQL: Select criteria for two tables, compare 1 field, return using condition

These are the tables in the query. Want to compare the ID_Skills in the following 2 tables. And in the returning table from the select query, display ID_Skills with condition saying whether or not TrainingRequired (Yes/No)
tblEmployeeCurrentSkills
ID_EmployeeCurrentSkills ID_Employee ID_Skills
1 1 1
2 1 2
3 2 1
tblSkillsRequired
ID_SkillsRequired ID_Employee ID_Skills ID_Position
1 1 1 1
2 1 2 1
3 1 3 1
4 2 3 2
tblSkills
ID_Skills Skill
1 Reading
2 Wiring
3 Stapling
tblPosition
ID_Position Position
1 Tech1
2 Stapler
tblEmployee
ID_Employee EmployeeName
1 Hannah
2 Bob
SQL for qrySkillsGap table - determines whether training is necessary
SELECT tblEmployee.[Employee Name],
tblSkillsRequired.ID_Skills,
tblSkills.Skill,
IIf([tblEmployeeCurrentSkills].[ID_Skills]
Like [tblSkillsRequired].[ID_Skills],"No","Yes") AS TrainingRequired
FROM (tblSkills
INNER JOIN tblSkillsRequired
ON tblSkills.ID_Skills = tblSkillsRequired.ID_Skills)
INNER JOIN (tblEmployee INNER JOIN tblEmployeeCurrentSkills
ON tblEmployee.ID_Employee = tblEmployeeCurrentSkills.ID_Employee)
ON tblSkills.ID_Skills = tblEmployeeCurrentSkills.ID_Skills;
This is the current output:
EmployeeName ID_Skill TrainingRequired
Hannah 1 No
Hannah 1 No
Hannah 2 No
Bob 1 No
Bob 1 No
I want it to display this:
EmployeeName ID_Skill TrainingRequired
Hannah 1 No
Hannah 2 No
Hannah 3 Yes
Bob 1 No
Bob 3 Yes
Thanks for any help!
I was able to create the tables you provided and used a union to bring together the employee skills and required skills.
SELECT te.EmployeeName
, emp.ID_Skills
, CASE WHEN MIN(emp.TrainingRequired) = 0 THEN 'No'
ELSE 'Yes'
END AS TrainingRequired
FROM dbo.tblEmployee AS te
JOIN (SELECT tecs.ID_Employee
, tecs.ID_Skills
, 0 AS TrainingRequired
FROM dbo.tblEmployeeCurrentSkills AS tecs
UNION
SELECT tsr.ID_Employee
, tsr.ID_Skills
, 1 AS TrainingRequired
FROM dbo.tblSkillsRequired AS tsr
) emp
ON te.ID_Employee = emp.ID_Employee
GROUP BY te.ID_Employee
, te.EmployeeName
, emp.ID_Skills
ORDER BY te.ID_Employee
, emp.ID_Skills

Selecting rows and filler (null data)

I have a table that looks like this:
ReportID | TeamID | Inning | Runs
1 A 1 3
1 A 2 3
1 A 5 7
1 B 1 3
1 B 3 2
1 B 6 1
I need to select all of that data, plus null data for the missing innings. It also need to stop at the max Inning for both teams (i.e. teamB's highest inning is 6, so I would collect 6 rows for both teamA and teamB yielding 12 total rows.)
For a visual, I need the output of the query to look like this:
ReportID | TeamID | Inning | Runs
1 A 1 3
1 A 2 3
1 A 3 NULL
1 A 4 NULL
1 A 5 7
1 A 6 NULL
1 B 1 3
1 B 2 NULL
1 B 3 2
1 B 4 NULL
1 B 5 NULL
1 B 6 1
Is there anyway to do this with just a query? Modifying the original table to add the null values is not an option.
Self join to generate the permutations of reports and teams
Left self join to generate hits which might be nullable.
This is probably a lot more efficient if it's done outside of SQL
SELECT ins.ReportID, teams.TeamID, ins.inning, score.Runs
FROM games as ins
JOIN games AS teams
ON ins.ReportID = teams.ReportID
LEFT JOIN games AS score
ON ins.ReportID = score.ReportID
AND teams.TeamID = score.TeamID
AND ins.inning = score.inning
GROUP BY ins.ReportID, teams.TeamID, ins.inning;

Need hierarichal data from 3 tables in SQL Server

I have following tables:
UserMaster:
UserId Int, UserName Varchar(200),AddedBy Int
UserId EmpName AddedBy
1 admin 0
2 SubAdmin1 1
3 SubAdmin2 1
4 Vikas 2
5 Mohit 4
6 Atul 5
7 Vishal 6
8 Mani 3
9 Sunny 8
SalesMaster:
SalesId Int, UserId Int (FK_UserMaster_UserId) , Price Int
SalesId UserId Price
1 1 100
2 2 200
3 3 300
4 4 500
5 5 100
6 6 200
7 7 111
8 8 222
9 9 333
Case 1: Now I want the price total of all the users who are under the one particular user and its own price also.
Means If i consider UserId=1 , Then the price will be calculated for all users where Column value in AddedBy=1
and their lower level employees.
Means the total Price of users will be calulated for the users having UserId are: 1,2,3,4,5,6,7,8,9.
Case 2: Similarly, If i want to calculate the total price under UserId=3(SubAdmin2) then the total price from the salesMaster will be calculated for the Users having UserId are: 3,8,9
The Result of first Case should be:
UserId Price
1 2066
The Result of Second Case should be:
UserId Price
3 300+222+333
Please Help
Thanks & Regards
Nitin
with cte as (
select #UserId as UserId
union all
select um.UserId
from UserMaster as um
inner join cte as c on c.UserId = um.AddedBy
)
select sum(s.Price)
from cte as c
inner join SalesMaster as s on s.UserId = c.UserId
sql fiddle demo