Move rows to columns in SQL Server - sql

I have tried using PIVOT and other methods to fix a problem, but I seem to be stuck.
CustomerID Question Answer
...........................................................
469494 Q111 Mottok e-post
469494 Q125 Ja
469494 Q112 Ja
469494 Q113 Ingeniør eller bachelor i tekn
469494 Q16 6 Meget bra
I need each customer row to inlude all answers, and the columns to be the value of Question key. Like This:
CustomerID Q111 Q125 Q112 Q113 (etc)
.........................................................................................
469494 Mottok e-post Ja Ja Ingeniør eller bachelor i tekn
There are multiple customers answering. And some answers are freetext.
My main problem here is that The Questions - and ofcourse - the answers are dynamic. They are answering a questionnaire, and this is a report that should be able to run and extract info for a specific questionnaire, with different Question keys and number of questions may also vary.
I didn't manage to do this with the PIVOT function, as the values differ.

Related

SQL Error: ambiguous column nameor syntax error [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Tried to change my code many times, need help with these errors, please!
Result: ambiguous column name: main.Guides.Guide_ID
SELECT *
FROM Guides
INNER JOIN Guides ON Guides_Countries.Guide_ID = Guides_Countries.Guide_ID
INNER JOIN Countries ON Countries.Country_ID = Guides_Countries.Country_ID
INNER JOIN Guides_Languages ON Guides.Guide_ID = Guides_Languages.Guide_ID
INNER JOIN Languages ON Languages.Language_ID = Guides_Languages.Language_ID
WHERE Countries.Name="Kazakhstan" AND (Languages.Name="German" OR Languages.Name="English") AND Guides.Guide_ID NOT IN
(SELECT Guide_ID
FROM GuidesUnavailableDates
INNER JOIN GuidesUnavailableDates ON GuidesUnavailableDates.UnDate_G_ID=Guides_UnDate.UnDate_G_ID
WHERE (Start_date<="21/06/2020" and End_date>="21/06/2020")
OR (Start_date<="30/06/2020" and End_date>="30/06/2020")
OR (Start_date>="21/06/2020" and End_date<="30/06/2020")
)
;
You have multiple table names appearing multiple times in your FROM clauses. That is causing your problem. I think you want:
SELECT *
FROM Guides g JOIN
Guides_Countries gc
ON gc.Guide_ID = g.Guide_ID JOIN
Countries c
ON c.Country_ID = gc.Country_ID JOIN
Guides_Languages gl
ON g.Guide_ID = gl.Guide_ID JOIN
Languages l
ON l.Language_ID = gl.Language_ID
WHERE c.Name = 'Kazakhstan' AND
l.Name IN ('German', 'English') AND
g.Guide_ID NOT IN (SELECT gud.Guide_ID
FROM GuidesUnavailableDates gud
WHERE gud.Start_date <= '2020-06-30' AND
gud.End_date >= '2020-06-21'
);
Notes:
Guide_Countries is not in your FROM list although Guides is there twice.
IN is much simpler than mutiple ORs.
All columns are qualified so it is clear what table they are coming from.
All tables have simple table aliases which are abbreviations for the table names.
There is no need for a JOIN in the subquery.
Use well formatted dates.
I am guessing that the weird date logic is to find an overlap with the time period mentioned so I simplified the logic. (You haven't explained the logic, so this is a guess and your original code doesn't make sense.)
I strongly recommend using NOT EXISTS with subqueries rather than NOT IN. However, I did not change the code here (mostly because I can't really tell what the subquery is supposed to be doing).

Google's Big Query using SQL: Associate the assignee name and harmonized assignee name when there are multiple assignees

My goal is to create a table from Google's Big Query patents-public-data.patents.publications_201710 table using standard SQL that has one row for the publication_number, assignee and assignee_harmonized.name where the publication_number is repeated for records that have multiple assignees. Here's an example of my desired output:
publication_number|assignee|assignee_harm
US-6044964-A|Sony Corporation|SONY CORP
US-6044964-A|Digital Audio Disc Corporation|DIGITAL AUDIO DISC CORP
US-8746747-B2|IPS Corporation—Weld-On Division|IPS CORPORATION—WELD ON DIVISION
US-8746747-B2|null|MCPHERSON TERRY R
I've tried the following query based off of the UNNEST suggestion found in this post
#standard SQL
SELECT
p.publication_number,
p.assignee,
a.name AS assignee_harm
FROM
`patents-public-data.patents.publications_201710` AS p,
UNNEST(assignee_harmonized) AS a
WHERE
p.publication_number IN ('US-6044964-A',
'US-8746747-B2')
However, the output appears as follows:
row|publication_number|assignee|assignee_harm
1|US-6044964-A|Sony Corporation|SONY CORP
||Digital Audio Disc Corporation|
2|US-6044964-A|Sony Corporation|DIGITAL AUDIO DISC CORP
||Digital Audio Disc Corporation|
3|US-8746747-B2|IPS Corporation—Weld-On Division|MCPHERSON TERRY R
4|US-8746747-B2|IPS Corporation—Weld-On Division|IPS CORPORATION—WELD ON DIVISION
You can see that the "Sony Corporation" assignee is inappropriately associated with the "DIGITAL AUDIO DISC CORP" harmonized name in row 2 with a similar issue appearing in row 3. Also, rows 1 and 2 contain two lines each but don't repeat the publication_number identifier. I don't see a straightforward way to do this because the number of "assignee" doesn't always equal the number of "assignee_harmonized.name" and they don't always appear in the same order (otherwise I could try creating two tables and merging them somehow). On the other hand, there has to be a way to associate the "assignee" variable with its harmonized value "assignee_harmonized.name", otherwise the purpose of having a harmonized value is lost. Could you please suggest a query (or set of queries) that will produce the desired output when there are either multiple "assignee" or multiple "assignee_harmonized.name" or both?
You're querying for a string and two arrays - the whole thing basically looks like this:
{
"publication_number": "US-8746747-B2",
"assignee": [
"IPS Corporation—Weld-On Division"
],
"assignee_harm": [
"MCPHERSON TERRY R",
"IPS CORPORATION—WELD ON DIVISION"
]
}
So that's the data and you somehow need to decide how to treat the combination of them ... either you cross join everything:
#standard SQL
SELECT
p.publication_number,
assignee,
assignee_harmonized.name AS assignee_harm
FROM
`patents-public-data.patents.publications_201710` AS p
,p.assignee assignee
,p.assignee_harmonized AS assignee_harmonized
WHERE
p.publication_number IN ('US-6044964-A','US-8746747-B2')
.. which gives you relational data .. or you leave it as two separate arrays:
#standard SQL
SELECT
p.publication_number,
assignee,
ARRAY( (SELECT name FROM p.assignee_harmonized)) AS assignee_harm
FROM
`patents-public-data.patents.publications_201710` AS p
WHERE
p.publication_number IN ('US-6044964-A','US-8746747-B2')
You can save this nested result as a table in bq as well.

SQL - Remove Duplicates in Single Field

SELECT Company.CompanyName
,Student.Status
,Student.Level
,Student.PlacementYear
,Company.CompanyCode
,Company.HREmail
,Company.Telephone
,Company.HRContact
,PlacedStudents.DateAdded
FROM Student
RIGHT JOIN (Company INNER JOIN PlacedStudents
ON Company.CompanyCode = PlacedStudents.CompanyCode)
ON Student.StudentNo = PlacedStudents.StudentNo
WHERE (((Student.PlacementYear)=" & Year & "))
AND((Student.Status)<>'Still Seeking YOPE')
ORDER BY Company.CompanyName
I have this SQL Query which pulls HR Contacts from Companies where students are currently placed. However, there are multiple students at one company so when I run the query there are duplicates. I'm fairly new to SQL, I tried DISTINCT, however it didn't seem to do anything, the duplicates remained.
How can I remove duplicates in the CompanyCode field so that the Company only appears once when the query is run.
Below is an image of what happens when I run query. Hopefully this makes sense?
Any help would be appreciated.
This query should give you companies that have placed students:
SELECT Company.CompanyName
,Company.CompanyCode
,Company.HREmail
,Company.Telephone
,Company.HRContact
FROM Company
WHERE EXISTS (SELECT * FROM PlacedStudents INNER JOIN
Student ON Student.StudentNo = PlacedStudents.StudentNo
WHERE Company.CompanyCode = PlacedStudents.CompanyCode
AND Student.PlacementYear =" & Year & "
AND Student.Status <>'Still Seeking YOPE')
ORDER BY Company.CompanyName;
Your question is asking for HR Contacts from Companies where students are placed. I assume this means if you have 1, 2 or 1,000,000 students at a single company, you only want to see the company listed once?
Your current query is returning information from STUDENT and PLACEDSTUDENTS which is going to result in output like
COMPANY_A STUDENT01 .........
COMPANY_A STUDENT02 .........
COMPANY_A STUDENT03 .........
and so on.
If so, and taking a best guess (since I can't know what's in STUDENT or PLACEDSTUDENTS tables), try not including anything related to STUDENT in the SELECT.
SELECT DISTINCT Company.CompanyName, Company.CompanyCode, Company.HREmail,
Company.Telephone, Company.HRContact FROM
I'll be happy to help more if you can provide more information about the structure of the tables and some examples of data, AND what you actually want from the query.

Produce a Query viewing multiple tables

I have been given a database, the structure and data values are all unchangable and have been provided with a question.
Produce a query to list the holiday code, holiday description, holiday duration and site description for all holidays which visit site code 101. Your answer must not assume that site code 101 will always have the same site description.
I am confused on how to tackle this question. I have tried Multiple joins, different dot notation and googled the question to hell and back. Any help?
Table 1 - Holiday_Details
Holiday_Code - Country_Visited - Holiday_Duration - Holiday_Desc - Rating_Code - Cost
Table 2 - Site_Of_Holiday
Site_Description - Site_Code
Table 3 - Site_Visited
Holiday_Code - Site_Code
Comments have asked for previous attempts. This was my first.
SELECT holiday_code,
holiday_desc,
holiday_duration site_of_holiday.Site_Name
FROM holiday_details
JOIN site_visited
ON holiday_code = site_visited.holiday_code
JOIN site_of_holiday
ON site_visited.site_code = site_of_holiday.site_code
WHERE site_of_holiday.site_code = 101;
For future reference, you'll get a better response if you post a lot more detail about your failed attempts. By that, I mean code. Using SO to solve your homework assignments is frowned upon but, like a commenter said, once you've wracked your brain we're willing to help.
You seem like you may have actually tried real hard, so I'll throw you a bone...
The trick to navigating multiple tables is to find the "pairs" of matching columns. In this case you want to find a path between the tables Site_Of_Holiday (which has Site_Description) and Holiday_Details (which has everything else).
The columns that match between each pair of tables are:
Holiday_Code is found in both Site_Visited and Holiday_Details
Site_Code is found in both Site_Of_Holiday and Site_Visited
This allows you to build a path between the tables that contain all of the columns we want in the output. You would do this, in this case, using INNER JOINs across those matching column pairs.
Once you've joined the tables, think of the result like a giant table whose columns include all columns from all three tables (prefixed with whatever you 'name' the table during the joins). Now you just filter on the Site_Code with the usual WHERE clause.
Here's the full example - let me know if it works for you:
SELECT hd.Holiday_Code, hd.Holiday_Desc, hd.Holiday_Duration, soh.Site_Description
FROM Holiday_Details hd
INNER JOIN Site_Visited sv ON hd.Holiday_Code = sv.Holiday_Code
INNER JOIN Site_Of_Holiday soh ON sv.Site_Code = soh.Site_Code
WHERE sv.Site_Code = 101
Good luck!
P.S. In case any Americans get a similar assignment, here's the translation ;-)
SELECT vd.Vacation_Code, vd.Vacation_Desc, vd.Vacation_Duration, sov.Site_Description
FROM Vacation_Details vd
INNER JOIN Site_Visited sv ON vd.Vacation_Code = sv.Vacation_Code
INNER JOIN Site_Of_Vacation sov ON sv.Site_Code = sov.Site_Code
WHERE sv.Site_Code = 101

Problem with query

I've four tables:
characters
guid
name
gender
class
race
online
character_arena_stats
guid
personal_rating
matchmaker_rating
arena_team_member
arenateamid
played_season
played_week
wons_season
wons_week
arena_team
arenateamid
captain_guid
and I need to get character details(race,class,name,gender,online) and team information(personal_rating,matchmaker_rating,played_season,played_week,wons_season,wons_week,captain_guid), but can't get it working. My query is:
$result=mysql_query("SELECT
c.guid,
c.name,
c.gender,
c.class,
c.online,
c.race,
atm.guid,
atm.played_season,
atm.played_week,
atm.wons_season,
atm.wons_week,
atm.arenateamid,
cas.personal_rating,
cas.guid,
cas.matchmaker_rating,
at.arenateamid,
at.captainguid
FROM
character_arena_stats cas,
arena_team_member atm,
characters c,
arena_team at
WHERE c.guid = cas.guid AND atm.arenateamid = ".$entry." AND at.arenateamid = ".$entry."");
It should return only members whose guid is equal to c.guid, cas.guid, atm,guid and those, whose atm.arenateamid is equal to at.arenateamid. Insted, it returns a lot of random members.
Thanks and sorry for my english.
Since you're not specifying how records in the arena tables should join to records in the character tables, you're getting a cross join, which returns every combination of character records with arena records.
When you say "I want to get them all," what exactly do you mean? Find a starting point for your query. For example: are you looking for all characters, organized by team, with their details and arena stats? Or, for each character, all the teams on which they participate?
Defining the requirements a little more clearly will help us suggest solutions. :)
Update: Actually, having read the query a little more closely, I believe I can infer what you're looking for:
SELECT
c.guid,
c.name,
c.gender,
c.class,
c.online,
c.race,
atm.guid
atm.played_season,
atm.played_week,
atm.wons_season,
atm.wons_week,
atm.arenateamid,
cas.personal_rating,
cas.guid,
cas.matchmaker_rating,
at.arenateamid,
at.captainguid
FROM
character_arena_stats cas,
arena_team_member atm,
characters c,
arena_team at
WHERE c.guid = cas.guid
and c.guid = atm.guid
and atm.arenateamid = at.arenateamid
AND at.arenateamid = ".$entry."
Note that the Arena Team and Character tables are now joined based on the team captain's GUID - this will avoid the cross join ("random rows") problem. Also, Arena Team Members is now joined to Arena Teams, and the filter parameter is only checked against the Teams table.
Not sure this will give you precisely what you want without knowing more about your data and requirements - I believe what it will give you is a list of each team captain, their arena stats, along with their team and team members' stats. Hopefully this will move you forward. Good luck!
uhh mate not sure what you got there,... to lazy myself to write the query for you, have a look again at dev.mysql.com refs should be straight forwared.
also your character_arena_stats table, shouldn't there be a ref to a arena table or something?
guid
arena_id ?
personal_rating
matchmaker_rating
see more here for normalization
Yeah, I am not really sure exactly what you're trying to do, but based on the description ...
Your Model seems to be all wrong and will never produce the results you are looking for. For instance, there are no Keys tying arena_team and arena_team_member to characters and character_arena_stats.
Secondly, this condition:
"WHERE c.guid = cas.guid AND atm.arenateamid = ".$entry." AND at.arenateamid = ".$entry);
is incorrect for this statement: "It should return only members ... whose atm.arenateamid is equal to at.arenateamid".
Rather, it could be rewritten as follows:
"WHERE c.guid = cas.guid AND atm.arenateamid = at.arenateamid AND atm.arenateamid = ".$entry);
Regardless though, because of the aforementioned reasons, the query will never returned expected results, at least based on what I understood from your post.
SIDE NOTE: This is PHP code, so I do not know why you are tagging it as jQuery.
Good Luck,