Fetch results of joined tables as columns in postgres - sql

I trying to figure out a way to generate a SQL query, to be used in a view, to generate an Excel like format for parent-child relationship.
I have the following tables
Person
id
name
email
accepted
1
A
--
--
2
B
--
--
3
C
--
--
Guest
id
name
accepted
id_person (foreign_key -> person.id)
1
AGuest1
---
1
2
BGuest1
---
2
3
BGuest2
---
2
4
CGuest1
---
3
5
CGuest2
---
3
6
CGuest3
---
3
A person can have multiple guests accompanying him/her.
What I want to do is generate a SQL that gives me the following result:
Person Name
Guest 1 Name
Guest 2 Name
Guest 3 Name
A
AGuest1
--
--
B
BGuest1
BGuest2
--
C
CGuest1
CGuest2
CGuest3
I can generate two separate queries that will generate a list of rows with that information but I am struggling to generate multiple columns based on the information that I have.
I have looked into crosstab() for postgres, but so far I have no luck with generating anything that would like this.
Any help or pointers in the right direction would be helpful, thank you!

You can use CROSSTAB:
SELECT *
FROM CROSSTAB (
'SELECT p.name, g.name, g.name
FROM person p JOIN guest g
ON p.id = g.id_person
ORDER BY 1,2')
AS ("Person Name" varchar(100), "Guest 1 Name" varchar(100),
"Guest 2 Name" varchar(100), "Guest 3 Name" varchar(100));
Please note: This will work for 1 to 3 guest like you described. In case more guests per person are possible, you need to extend this.
I created a working example here: db<>fiddle

Related

Is there a way to return a partial blank row in SQL when joining tables through automation?

For my project, I have 2 tables. Initially I inner joined both tables (table 1 and 2) via an inner join. However, I wanted an outcome as seen in table 4 where the repeated value from table 1 is left blank instead.
For table 2, the number of rows will always vary. There will always only be 1 department ID attached to numerous function IDs. Is there a query then where regardless of the number of function IDs, the department ID will only appear as the first row as seen in table 4?
(I think to many, this might seem weird and frankly not clean data, but for mail merges within word, it is easier to field code when the data is presented this way to refrain sections from 'reprinting itself'.)
Current Code:
SELECT Table1.*, Table2.* FROM
INNER JOIN Table 2 ON Table1.DepartmentID = Table2.DepartmentID
Table 1:
Department ID
Department
1
XYZ
Table 2:
Department ID
Function ID
Function
1
1
ABC
1
2
DEF
Table 3 (inner joined):
Department ID
Department
FunctionID
Function
1
XYZ
1
ABC
1
XYZ
2
DEF
Table 4 (desired):
Department ID
Department
FunctionID
Function
1
XYZ
1
ABC
2
DEF

SQL query in postgresql to produce pivot table report to turn columns into rows

Unsure how to create a pivot report query in postgres (newbie to postgres) based on the following tables/report layout.
Please note that I am not able to change the structure of these tables as out of my control.
STOCK_REF ( sr_id, stock_name )
STOCK_INVENTORY ( si_id, sr_id, stock_count ) * where sr_id here is a foreign key constraint
Sample data for each table may include the following:
STOCK_REF
1 GUITAR
2 BASS
3 DRUMS
4 KEYBOARDS
STOCK_INVENTORY
1 1 10
2 2 5
3 3 2
4 4 15
Using the above two tables, I need to produce a report that looks like:
STOCK NAME COUNT
--------------------------- --------
GUITAR 10
BASS 5
DRUMS 2
KEYBOARDS 15
which is like a pivot table.
The thing is, I can write the query that will produce the stock name as columns with counts but I actually need to have the stock name and counts as rows, like above.
Any help with this postgres query would be ideal
Try the query below. It's simple SQL. I think POSTGRES don't determine too much here...
SELECT stock_name AS "STOCK NAME", stock_count AS "COUNT"
FROM STOCK_REF INNER JOIN STOCK_INVENTORY
ON (STOCK_REF.sr_id = STOCK_INVENTORY.sr_id)

Querying SQL table with different values in same column with same ID

I have an SQL Server 2012 table with ID, First Name and Last name. The ID is unique per person but due to an error in the historical feed, different people were assigned the same id.
------------------------------
ID FirstName LastName
------------------------------
1 ABC M
1 ABC M
1 ABC M
1 ABC N
2 BCD S
3 CDE T
4 DEF T
4 DEG T
In this case, the people with ID’s 1 are different (their last name is clearly different) but they have the same ID. How do I query and get the result? The table in this case has millions of rows. If it was a smaller table, I would probably have queried all ID’s with a count > 1 and filtered them in an excel.
What I am trying to do is, get a list of all such ID's which have been assigned to two different users.
Any ideas or help would be very appreciated.
Edit: I dont think I framed the question very well.
There are two ID's which are present multiple time. 1 and 4. The rows with id 4 are identical. I dont want this in my result. The rows with ID 1, although the first name is same, the last name is different for 1 row. I want only those ID's whose ID is same but one of the first or last names is different.
I tried loading ID's which have multiple occurrences into a temp table and tried to compare it against the parent table albeit unsuccessfully. Any other ideas that I can try and implement?
SELECT
ID
FROM
<<Table>>
GROUP BY
ID
HAVING
COUNT(*) > 1;
SELECT *
FROM myTable
WHERE ID IN (
SELECT ID
FROM myTable
GROUP BY ID
HAVING MAX(LastName) <> MIN(LastName) OR MAX(FirstName) <> MIN(FirstName)
)
ORDER BY ID, LASTNAME

Creating a SQL view that contains columns which have different data types

I am trying to create a SQL view which contains columns from different tables; the columns are different data types.
For example;
I have table a with a column that contains usernames. The data type of this column is nvarchar.
I then have table b, which has a column that contains whether a document was printed in colour or not – the data is either yes or no. The data type of this column is bit.
I want the view to show both the above columns side by side, so I can then pull the information into Excel for reporting purposes.
I am pretty new to SQL so I am learning as I go along.
Like PM77-1 said, you'll have to have some way to tie the two tables together. For example, if your table b also has the userID of the person who printed the document out, your tables would look like this:
Table A Table B
---------------------------- -----------------------------------
userID userName docID docName inColor userID
---------------------------- -----------------------------------
1 userName1 1 docName1 1 1
2 userName2 2 docName2 0 2
3 userName3 1 docName1 1 2
3 docName3 0 1
3 docName3 1 2
2 docName2 1 3
and your query could look like this:
SELECT a.userName, b.docName, b.inColor FROM a INNER JOIN b ON a.userID = b.userID ORDER BY a.userName, b.inColor;

Normalise/join SQL Server tables

I have inherited a SQL server database which isn't normalised and is giving me headaches. I am not very experienced in SQL and maybe asking stupid questions but would appreciate any advice on how to go forward with the below scenarios.
I have three tables as follows:-
A table of results:
**ResId CompId Name Result**
1 1 Band A 2
2 1 Band B 1
3 1 Band C 3
4 2 Band A* 2
5 2 Band B 1
6 2 Band C 3
A table of Bands current names:
**BandId BandName**
1 Band A
2 Band B
3 Band C
A table of names the bands were previously known as (linked on BandId):
**oldBandId BandId oldBandName**
1 1 Band A*
2 1 Band a
2 2 Band b
I am looking to consolidate the list of band names in the results table, replacing the band name with a bandId however the result table contains band names from both tables. First question should I create some sort of join table and use this as the bandId in the results table? If so What do I need in this join table, is it just a psuedo-Id of bandId/oldBandId and the table name concatenated then this placed in the results table?
I am then looking to use a query to select all results where the user selects the band by any name variant (new or old) and returns the results including all names linked with the band i.e. choosing Band A would return the results for both Band A and Band A*.
Thanks in advance
Steve
I like the idea of using the band id in the results table. I would suggest eliminating the "old band name" table and replace it with a table of band aliases, since that sounds more like what you want. The band alias table would just have the band id and an one alias per row.
I think your current db structure is fine enough - I can't think of any way to improve on it, without complicating it further (especially if you want to retain the old band names).
You can just write a query as so for your need -
select * from results
where Name = #bandName or
Name in (select oldBandName
from oldBands
where BandId in (select BandId
from Bands
where BandName = #bandName))