How to get multi columns via subquery? - sql-server-2008

I want to get members and their photos. Every member has 2 photos. (I am not talking about profile image)
There are 2 tables named as Members and MemberPhotos.
Here is my query which doesn't work(expectedly):
SELECT
M.Name as MemberName,
M.LastName as MemberLastName,
(
SELECT
TOP 1
MP.PhotoName
FROM
MemberPhotos MP
WHERE
MP.MemberID = M.ID
AND
MP.IsFirst = 1
) as MemberFirstPhoto,
(
SELECT
TOP 1
MP.PhotoName
FROM
MemberPhotos MP
WHERE
MP.MemberID = M.ID
AND
MP.IsFirst = 0
) as MemberSecondPhoto,
FROM
Members M
Maybe somebody going to say that I should use inner join instead, I don't want to use inner join, if I use it I get data multiple like:
Name Surname PhotoName
Bill Gates bill.png
Bill Gates bill2.png
Steve Jobs steve.jpg
Steve Jobs steve2.jpg
What do you recommend me about query?
Thanks.
EDIT:
Here is the output I want to get:
Name Surname FirstPhoto SecondPhoto
Bill Gates bill.png bill2.png
Steve Jobs steve.jpg steve2.png

The only issue with your example query is that you have an extra comma after
as MemberSecondPhoto
If you remove this it works fine.
SQL Fiddle with demo.
However, while that query is working now, because you know that each member only has two photos, you can use a much simpler query:
SELECT
M.Name as MemberName,
M.LastName as MemberLastName,
MPF.PhotoName as MemberFirstPhoto,
MPS.PhotoName as MemberSecondPhoto
FROM Members M
LEFT JOIN MemberPhotos MPF ON M.ID = MPF.MemberID AND MPF.IsFirst = 1
LEFT JOIN MemberPhotos MPS ON M.ID = MPS.MemberID AND MPS.IsFirst = 0
SQL Fiddle with demo.

Related

Query involving join - combine data from 2 of our tables

We need to combine data from 2 of our tables - active_deals and deal_display_controls. The (relevant) columns in each of them are:
`active_deals` : `deal_id`, `region_code`
`deal_display_controls` : `deal_id`, `display_control_id`
The query needs to fetch all count of all the active deals having a given display_control_id and group them by their region_code (group by region code). Along with this, it also needs to group the active deals by region code (without the display_control_id constraint)
So, if the active deals tables looks like:
deal_id region_code
d1 US
d2 CA
d3 US
And the deal_display_controls looks like:
`deal_id` `display_control_id`
d1 dc1
d2 dc1
d3 dc2
d4 dc1
Then for a given display control id = “dc1”
The query should output:
`region_code` `count_of_active_deals_with_given_display_control_for_region_code `count_of_active_deals_for_region_code`
US 1 2
CA 1 1
I could do this by splitting the above question into 2 parts and writing individual queries for each part:
Part 1: To get the active deals for a given display_control_id and group by region code
Query for the same:
select count(*), region_code from active_deals join deal_display_controls on active_deals.bin_deal_id=deal_display_controls.deal_id where deal_display_controls.display_control_id=0xc04e20724f5f49c9a285cb3c98d777b4 group by active_deals.region_code;
O/p:
`region_code` `count_of_active_deals_with_given_display_control_for_region_code
US 1
CA 1
Part2: To get the active deals and group by region code
Query for the same:
select count(*), region_code from active_deals join deal_display_controls on active_deals.bin_deal_id=deal_display_controls.deal_id group by active_deals.region_code;
O/p:
`region_code` `count_of_active_deals_for_region_code`
US 2
CA 1
I need to way to combine these 2 queries into a single query. Is it possible to do this?
while counting you can add additional condition of control_id
select d.region_code
, count(distinct d.deal_id) count_of_active_deals_for_region_code
, SUM(c.display_control_id = 'dc1') count_of_active_deals_with_given_display_control_for_region_code
from active_deals d
left
join deal_display_controls c
on d.deal_id = c.deal_id
group
by d.region_code
Fiddle: http://sqlfiddle.com/#!9/904670/2
I think you want a join with conditional aggregation:
select d.region_code,
sum(ad.display_control_id = 1),
count(*)
from active_deals ad join
deals d
on ad.deal_id = d.deal_id
group by d.region_code

Multiple joins on same table

I'm trying to achieve a query which seems simple but I can't make it work correctly. Here's my database tables structures:
members
-> id
-> last_name
-> first_name
activities
-> id
registrations
-> id
-> member_id
tandems
-> id
-> activitie_id
-> registration_member_one
-> registration_member_two
Here's what i want to achieve:
Mutliple members can register to an activity. Then, i group the registrations by tandems. I want a view with all the tandems listed and there's my problem. When I try a query, it gives me multiple rows, duplicated many times.
Below, an example of the table I want to have:
tandems.id | activities.id | registration_member_one.members.last_name | registration_member_two.members.last_name
1 | 3 | John Doe | Jane Doe
Here's the query I'm working on:
SELECT
tandems.*,
memberOne.id, memberOne.last_name, memberOne.first_name,
memberTwo.id, memberTwo.last_name, memberTwo.first_name,
memberOne_registration.member_id as memberOne,
memberTwo_registration.member_id as memberTwo
FROM tandems
JOIN registrations as memberOne_registration
ON memberOne_registration.member_id = tandems.registration_member_one
JOIN members as memberOne ON memberOne.id = memberOne_registration.member_id
JOIN registrations as memberTwo_registration
ON memberTwo_registration.member_id = tandems.registration_member_two
JOIN members as memberTwo ON memberTwo.id = memberTwo_registration.member_id
WHERE activitie_id = 3;
Any help appreciated!
The error is caused by joining wrong column (member_id) of registrations table with tandems table, instead column registrations.id should be used.
SELECT
tandems.*,
memberOne.id, memberOne.last_name, memberOne.first_name,
memberTwo.id, memberTwo.last_name, memberTwo.first_name,
memberOne_registration.id as memberOne,
memberTwo_registration.id as memberTwo
FROM tandems
JOIN registrations as memberOne_registration ON memberOne_registration.id = tandems.registration_member_one
JOIN members as memberOne ON memberOne.id = memberOne_registration.member_id
JOIN registrations as memberTwo_registration ON memberTwo_registration.id = tandems.registration_member_two
JOIN members as memberTwo ON memberTwo.id = memberTwo_registration.member_id
WHERE activitie_id = 3;
Although other query is virtually the same, I hate working with unnecessarily long alias names so worked with "r1" and "r2" for the two instances of the registration table, and "m1" and "m2" for the members joining context.
SELECT
t.id,
t.activitie_id,
m1.last_name LastName1,
m1.first_name FirstName1,
m2.last_name LastName2,
m2.first_name FirstName2
FROM
tandems t
LEFT join registrations r1
ON t.registration_member_one = r1.id
LEFT JOIN members m1
ON r1.member_id = m1.id
LEFT join registrations r2
ON t.registration_member_two = m2.id
LEFT JOIN members m2
ON r2.member_id = m2.id
WHERE
t.activitie_id = 3;
To help you on this and in the future... Although mentally done, I try to mentally draw out how do I get the pieces together from the first table downstream. This can be seen too by the visual indentation almost like a tree view extension from T to R1 to M1, then R2 to M2 is a different branch. I also prefer to list the left table/alias.column = right table/alias.column in the join condition. How does T get to R1, then how does R1 get to M1.
In this, I used LEFT JOIN to each respective registration and member -- just-in-case only one person registered and a second may be pending. Not sure how your registration is actually structured.

Alter columns from selected result table in MYSQL

Here the things,I want to join table 'responsibilities' with fields Name, Direct, Supervise:
Name | Direct | Supervise
ABC 2 4
and table 'positions' with positionCode, positionID:
positionCode | positionID
HR/HRM 2
HR/MN 4
The selected result table will be some thing like this.
Name | Direct | Supervise
ABC HR/HRM HR/MN
The 'Direct' and 'Supervise' column should be positionCode from 'positions' table. Is there an all-in-one query to output this result? Or I have to query 2 times ?
Try this Query,
SELECT r.Name,
p1.positionCode AS Direct,
p2.positionCode AS Supervise
FROM responsibilities r
LEFT JOIN positions p1
ON r.Direct = p1.positionID
LEFT JOIN positions p2
ON r.Supervise = p2.positionID
Output: SEE SQLFiddle DEMO
I think you can join responsibilities twice to the positions table:
SELECT r.Name,
COALESCE(p1.positionCode, 'Direct is N/A') AS Direct,
COALESCE(p2.positionCode, 'Supervise is N/A') AS Supervise
FROM responsibilities r
LEFT JOIN positions p1
ON r.Direct = p1.positionID
LEFT JOIN positions p2
ON r.Supervise = p2.positionID
Follow the link below for a running demo:
SQLFiddle
Try following Query, It should work
select R.Name,(select P.positionCode where R.Direct=P.positionID) as
Direct,(select P.positionCode where R.Supervise=P.positionID) as
Supervise from Responsibilites R, Positions P;
check out this SQL Fiddle for proof that this query works:
http://sqlfiddle.com/#!9/13845c/4/0
Basically, the query looks as follows:
SELECT r.Name, p1.positionCode As Direct, p2.positionCode as Supervise
FROM responsibilities r
LEFT JOIN positions p1 ON r.Direct = p1.positionID
LEFT JOIN positions p2 ON r.Supervise = p2.positionID

opinion about a query

If I have this piece of schema:
Doctor(license_no, doctor_name, specialty)
Patient(pat_id, pat_name, pat_address, pat_phone, date_of_birth)
Visit(license_no, pat_id, date, type, diagnosis, charge)
and I want to get the amount of money that Dr. Davy Jones has earned,
is the following query logically right? N.B it's running in SQL
SELECT SUM(charge)
FROM Visit v INNER JOIN Doctor d
ON (d.licence_no = v.licence_no AND doctor_name = 'davy jones')
I'd write it slightly different to account for the case where davy jones has seen no patients.
SELECT SUM(v.charge)
FROM Doctor d
LEFT JOIN Visit v
ON d.license_no = v.license_no
WHERE d.doctor_name = 'davy jones';
Yes :)
Just made a quick test.
Since you alias the table "Visit" to "v" you should also use the alias when specifying the column (v.charge). Also your inner join condition should specify only the join condition, and not the limiting clause, which should be specified as a WHERE condition. See this example:
SELECT SUM(v.charge)
FROM Visit v INNER JOIN Doctor d
ON (d.licence_no = v.licence_no)
WHERE d.doctor_name = 'davy jones';

Mysql eliminate user based on conditions

I asked this last week over the weekend and it got buried in the archives before anyone could answer. So forgive me if you've already seen this.
I teach classes and want to be able to select those students who have taken one class, but not another class. I have two tables: lessons_slots which is the table for every class such as:
--------------------
-ID name slots-
-1 basics 10 -
-2 advanced 10 -
-3 basics 10 -
---------------------
The other table is class_roll, which holds enrollment info, such as:
--------------------
-sID classid firstname lastname-
-1 1 Jo Schmo
-2 1 Person Two
...
-13 2 Jo Schmo
---------------------
What I want to do, I select everyone who has not had the advanced class (for example). I've tried doing
SELECT *
FROM lessons_slots
LEFT JOIN class_roll
ON lessons_slots.ID = class_roll.classid
WHERE lessons_slots.name != 'advanced'
But that doesn't work...All it does is eliminate that row, without eliminating the user. I want Jo Schmo, for example, to not show up in the results. Any ideas?
Not pretty, but works.
SELECT c.*
FROM lessons_slots l
join class_roll c on l.id=c.classid
where concat(firstname,lastname) not in (select concat(firstname,lastname)
from lessons_slots l
join class_roll c on l.id=c.classid where name='advanced')
SELECT * FROM class_roll cl LEFT JOIN lessons_slots ls
ON cl.classid = ls.id AND ls.name != 'advanced'
So you actually want to delete rows? Well then:
DELETE FROM class_roll cl LEFT JOIN lessons_slots ls
ON cl.classid = ls.id AND ls.name != 'advanced'
You could try something to the effect of
SELECT FirstName, LastName FROM class_roll
WHERE NOT EXISTS
(SELECT * FROM class_roll, lesson_slots
WHERE class_roll.classid = lesson_slots.ID
AND lesson_slots.name = 'advanced')
You can then use the result as the basis of a DELETE query.