Add columns to SQL query output - sql

I have searched this site and others, and I am unable to find a clear answer, so here I am. In the below query, I will get an output with a single column for the county. What I would like to do can only be described in Excel parlance as transpose the counties so each county for a brand family is in its own column. I have played around with using pivot, but unfortunately do not fully grasp what would be required. This is not my first query, but I am relatively new to SQL scripting, so please ask any clarification questions and I will do my best to answer.
Some of the brand families have 10 counties and some have 20, so some of the columns would be blank. This is for an in-house DB, not the SO DB, running on SQL Server 2008R2, FWIW.
The script is:
select distinct b.reckey as BrandFamilyKey, b.recname as BrandFamilyName,
g.recname as County
from territories as t
left join dbo.TerritoryBrandFamilies as tbf on tbf.TerritoryNid = t.TerritoryNid
left join Customers as c on c.TerritoryNid = t.TerritoryNid
left join GeographicAreas as g on g.GeoAreaNid = c.GeoAreaNid
left join brandfamilies as b on b.brandfamilynid = tbf.brandfamilynid
where t.activeflag = 1 AND C.GeoAreaNid IS NOT NULL and b.activeflag = 1
order by b.RecName,g.recname
the output would look like
brand family 1 county 1
brand family 1 county 2
brand family 1 county 3
What I would like to see is:
brand family 1 county 1 county 2 county 3

Related

Using TOP 1 (or CROSS APPLY) within multiple joins

I've reviewed multiple Q&A involving TOP 1 and CROSS APPLY (including the very informative 2043259), but I still can't figure out how to solve my issue. If I had a single join I'd be fine, but fitting TOP 1 into the middle of a chain of joins has stumped me.
I have four tables and one of the tables contains multiple matches when joining due to a previous bug (since fixed) that created new records in the table instead of updating existing records. In all cases, where there are multiple records, it is the top-most record that I want to use in one of my joins. I don't have access to the table to clean up the extraneous data, so I just have to deal with it.
The purpose of my query is to return a list of all "Buildings" managed by a particular person (user choses a person's name and they get back a list of all buildings managed by that person). My tables are:
Building (a list of all buildings):
BuildingId BuildingName
1 Oak Tree Lane
2 Lighthoue Court
3 Fairview Lane
4 Starview Heights
WebBuildingMapping (mapping of BuidingId from Building table, that is part of an old system, and corresponding WebBuildingId in another piece of software):
BuildingId WebBuildingId
1 201
2 202
3 203
4 204
WebBuildingContacts (list of ContactID for the building manager of each building). This is the table with duplicate values - where I want to choose the TOP 1. In sample data below, there are two references to WebBuidingId = 203 (row 3 & row 5) - I only want to use row 3 data in my join.
Id WebBuildingId ContactId
1 201 1301
2 202 1301
3 203 1303
4 204 1302
5 203 1302
Contacts (list of ContactIds and corresponding property manager Names)
ContactId FullName
1301 John
1302 Mike
1303 Judy
As noted, in the example above, the table WebBuildingContact has two entries for the building with a WebBuidingId = 203 (row 3 and row 5). In my query, I want to select the top one (row 3).
My original query for a list of buildings managed by 'Mike' is:
SELECT BuildingName
FROM Building bu
JOIN WebBuildingMapping wbm ON wbm.BuildingId = bu.BuildingId
JOIN WebBuildingContact wbc ON wbc.WebBuildingId = wbm.WebBuildingId
JOIN Contacts co ON co.ContactId = wbc.ContactId
WHERE co.FullName = 'Mike'
This returns 'Fairview Lane' and 'Starview Heights'; however, Judy manages 'Fairview Lane' (she's the top entry in the WebBuildingContacts table). To modify the query and eliminate row 5 in WebBuildingContacts from the join, I did the following:
SELECT BuildingName
FROM Building bu
JOIN WebBuildingMapping wbm ON wbm.BuildingId = bu.BuildingId
JOIN WebBuildingContact wbc ON wbc.WebBuildingId =
(
SELECT TOP 1 WebBuildingId
FROM WebBuildingContact
WHERE WebBuildingContact.WebBuildingId = wbm.WebBuildingId
)
JOIN Contacts co ON co.ContactId = wbc.ContactId
WHERE co.FullName = 'Mike'
When I try this; however, I get the same result set (ie it returns 'Mike' as manager for 2 buildings). I've also made various attempts to use CROSS APPLY but I just end up with 'The multi-part identifier could not be bound', which is a whole other rabbit hole to go down.
You could try this:
SELECT bu2.BuildingName
FROM building bu2
WHERE bu2.BuildingId IN
(SELECT MAX(bu.BuildingId)
FROM Building bu
JOIN WebBuildingMapping wbm ON wbm.BuildingId = bu.BuildingId
JOIN WebBuildingContact wbc ON wbc.WebBuildingId = wbm.WebBuildingId
JOIN Contacts co ON co.ContactId = wbc.ContactId
WHERE co.FullName = 'Mike'
);

How can I join three tables in MS Access SQL?

I have a simple table model with 3 tables but I am not able to join them in the way I need it.
Table: TOPIC
ID TITLE
1 Talk1
2 Talk2
3 Talk3
4 Talk4
Table: SPEAKER
ID NAME
20 Speaker20
21 Speaker21
22 Speaker22
23 Speaker23
Table: CONNECTOR
ID_TOPIC ID_SPEAKER
1 21
2 23
2 22
2 21
4 20
4 22
In Table CONNECTOR the Topics are getting assigned to speakers.
One Topic can be assigned to different speakers.
There can also be topics in the TOPIC table which are not assigned yet, like in this example topic 3.
What I need is an SQL which give me as result all topics from the TOPICS table with the assigned speakers with name but I also want the topics in the result list which are not assigned through the CONNECTOR table.
How should the join look like to get this result?
I did an example in Access and got this:
As you can see, the query lists all topics, even if there is no speaker assigned. The SQL code of my query is this:
SELECT TOPICS.Title, SPEAKER.SpeakerName
FROM SPEAKER RIGHT JOIN (CONNECTOR RIGHT JOIN TOPICS ON CONNECTOR.ID_TOPIC = TOPICS.Id) ON SPEAKER.ID = CONNECTOR.ID_SPEAKER;
Hope this helps
UPDATE: Please, note that in table SPEAKERS, I've used as fieldname SpeakerName instead of Name because Name it's a reserved word, and it can create some troubles using it.
Look for
SELECT TOPIC.TITLE, SPEAKER.NAME
FROM ( CONNECTOR
INNER JOIN TOPIC ON TOPIC.ID = CONNECTOR.ID_TOPIC)
INNER JOIN SPEAKER ON CONNECTOR.ID_SPEAKER = SPEAKER.ID
UNION ALL
SELECT NULL, SPEAKER.NAME
FROM SPEAKER
LEFT JOIN CONNECTOR ON CONNECTOR.ID_SPEAKER = SPEAKER.ID
WHERE CONNECTOR.ID_TOPIC Is Null
UNION ALL
SELECT TOPIC.TITLE, NULL
FROM TOPIC
LEFT JOIN CONNECTOR ON TOPIC.ID = CONNECTOR.ID_TOPIC
WHERE CONNECTOR.ID_TOPIC Is Null;

How to mix sql consults to make conditions to another one

I've the following tables
series_trailers:
ID EPISODEID CONTENT AUTHOR
-----------------------------
1 122383 url1 Peter
2 9999 url2 Ana
3 923822 stuff Jhon
4 122384 url3 Drake
series_episodes:
ID TITLE SERIESID
--------------------------------
122383 Episode 1 23
9999 Somethingweird 87
923822 Randomtitle 52
122384 Episode 2 23
series:
ID TITLE
-------------------
23 Stranger Things
87 Seriesname
512 Sometrashseries
As you can see there are three tables: one with the series info, one with the series' episodes and another one which contains urls that redirect to the episode's trailers. I'd like to get the lastest rows from series_trailers but without repeating the series where they're from.
I've tried with SELECT DISTINCT EPISODEID FROM series_trailers ORDER BY id DESCbut there are two rows with the same episodes' series so I'll get the seriies Stranger things twice. Summing up I'd like to display the lastest series with new urls but I don't want to get duplicated series (that's what i'd get with the sql above)
EDIT: What I'm supposed to get:
Last updated series:
Stranger Things
Seriesname
Sometrashseries
What I'd get with my sql code:
Stranger Things
Seriesname
Sometrashseries
Stranger Things (again)
If I understood correctly, here is the latest trailer for the latest episodes (latest as in the highest series ID / series_trailer ID, so most likely added lastest).
WITH MostRecentTrailers
AS (
SELECT MAX(st.ID) "TRAILERID"
,s.ID "SERIESID"
,s.TITLE "SERIESTITLE"
FROM series_trailers st
JOIN series_episodes se ON se.ID = st.EPISODEID
JOIN series s ON s.ID = se.SERIESID
GROUP BY s.ID
,s.TITLE
ORDER BY s.ID DESC
)
SELECT *
FROM MostRecentTrailers mrt
JOIN series_trailers st ON st.ID = mrt.TRAILERID
Let me know if that does it for ya.
Edit: Fixed some typo mistakes.
This gives you the trailer with the highest ID for each episode. This answer is based on the assumption that the episode with the highest ID is the latest one.
select id, content from series_trailer where episode_id in
(select max(id)
from series_episodes
group by seriesid)

Selecting more after group-by while using join

At the moment I am busy with two tables, Students and Classes. These two both contain a column project_group, a way to categorize multiple students from one class into smaller groups.
In the Students table there is a column City that states in which town/city students live, from the rows that have been filled there are already several cities occurring multiple times. The code I used to check how many times a city is being showed is this:
SELECT City, count(*)
FROM Students
GROUP BY City
Now the next thing I want to do is show per class in which cities the students live and how many live there, so for example a result like:
A | - | 2
A | New York | 3
A | Los Angeles | 1
B | - | 1
B | Miami | 2
B | Seattle | 1
Students and Classes can join each other on the column project_group but what I'm mostly interested in his using both the GROUP BY mentioned earlier, using the JOIN and also showing the results per class.
Thanks in advance,
KRAD
I'm not sure what the column name is for A and B in your example. I'm assuming Classes.Class in the following:
SELECT
C.Class
, S.City
, COUNT(S.*) AS Count
FROM
Classes AS C INNER JOIN
Students AS S ON C.Project_Group = S.Project_Group
GROUP BY
C.Class
, S.City
I managed to get it working. While doing some tests to see which exact error message it was that I got, I used this and managed to get it working. I now get an overview per class that shows how many people live in which city. This is the code used.
SELECT class_id, city, count(*) AS amount
FROM students, classes
WHERE students.project_group = classes.project_group
GROUP BY class_id, city
ORDER BY class_id

Help with SQL for Coldfusion query -- Getting back Counts, Totals or other Math

I am drawing a blank on how best to go about this task. I basically need to write some SQL for an Access db that will take data more or less in the following format:
State Lost Name
NY no A
NY no B
NY yes C
NY no D
MD yes E
MD yes F
VA no G
VA yes H
And I need a query to return the following:
State CountLost Total in State
NY 1 4
MD 2 2
VA 1 2
My current query works just fine in getting me the first two columns but I'm not quite sure how to append it to get this last column, showing the total in each state.
Either that or just as good would be State and a column for % lost per state:
State %Lost in State
NY 25%
MD 100%
VA 50%
Here's my current query getting me the first two columns. Hopefully, someone can help me sort out the rest...
SELECT lkuState.StateName as state, Count(lkuState.StateName) AS statecount
FROM lkuState INNER JOIN .........
GROUP BY lkuState.StateName, tblMain.Lost
HAVING ((tblMain.Lost)=false)
In most databases you could use a CASE statement (combined with SUM) to conditionally count the number Lost. But IIRC, Access does not support CASE and uses IIF instead.
SELECT s.StateName, COUNT(*) AS TotalInState,
SUM( IIF(m.Lost = 'yes', 1, 0) ) AS CountLost
FROM tblMain m INNER JOIN lkuState s ON s.StateID = m.StateID
GROUP BY s.StateName