Postgres key-value table, select values as columns - sql

I have the following table:
+----+---------+-------+
| id | Key | Value |
+----+---------+-------+
| 1 | name | Bob |
| 1 | surname | Test |
| 1 | car | Tesla |
| 2 | name | Mark |
| 2 | cat | Bobby |
+----+---------+-------+
Key can hold basically anything. I would like to arrive at the following output:
+----+------+---------+-------+-------+
| id | name | surname | car | cat |
+----+------+---------+-------+-------+
| 1 | Bob | Test | Tesla | |
| 2 | Mark | | | Bobby |
+----+------+---------+-------+-------+
Then I would like to merge the output with another table (based on the id).
Is it possible to do, if I don't know what the Key column holds? Values there are dynamic.
Could you point me to the right direction?

Related

SQL 'Sum' Text Fields, Delim with commas

I have a table like this:
+----+-------+-----------------+
| ID | Name | Email |
+----+-------+-----------------+
| 1 | Jane | Jane#doe.com |
| 2 | Will | Will#gmail.com |
| 3 | Will | wsj#example.com |
| 4 | Jerry | jj2#test.com |
+----+-------+-----------------+
Unfortunately I have records that are duplicates due to multiple emails. I would like to run a sql query to generate this:
+----+-------+---------------------------------+
| ID | Name | Email |
+----+-------+---------------------------------+
| 1 | Jane | Jane#doe.com |
| 2 | Will | Will#gmail.com, wsj#example.com |
| 4 | Jerry | jj2#test.com |
+----+-------+---------------------------------+
I know with numbers you'd do something like this, but I don't know how to 'sum' text fields:
SELECT *,
SUM(Number_Field) AS Number_Field,
FROM table
Thanks!
Edit: I am using MS Access

SQL Concat Id column with another column

Here is what I want to do:
I have this table
+----+-------------+
| id | data |
+----+-------------+
| 1 | max |
| 2 | linda |
| 3 | sam |
| 4 | henry |
+----+-------------+
and I want to Update the data with concatenating Id column with data, which will look like this:
+----+-------------+
| id | data |
+----+-------------+
| 1 | max1 |
| 2 | linda2 |
| 3 | sam3 |
| 4 | henry4 |
+----+-------------+
Sounds like this is basically what you want (T-SQL, Other platforms may have different methods for type conversion and concatenation):
update myTable
set data=data+convert(varchar(50),id)

SAS SQL: Many to many relationships with 2 tables BUT don't want multiple rows

I have two tables I need to join. These tables only share 1 field in common (ID, and it isn't unique). Is it possible to join these two tables but make it unique and keep all matching data in a row?
For example, I have two tables as follows:
+-------+----------+
| ID | NAME |
+-------+----------+
| A | Jack |
| A | Andy |
| A | Steve |
| A | Jay |
| B | Chris |
| B | Vicky |
| B | Emma |
+-------+----------+
And another table that is ONLY related by the ID column:
+-------+--------+
| ID | Age |
+-------+--------+
| A | 22 |
| A | 31 |
| A | 11 |
| B | 40 |
| B | 17 |
| B | 20 |
| B | 3 |
| B | 65 |
+-------+--------+
The end result I'd like to get is:
+-------+----------+++-------+
| ID | NAME | Age |
+-------+----------++-------+-
| A | Jack | 22 |
| A | Andy | 31 |
| A | Steve | 11 |
| A | Jay | null |
| B | Chris | 40 |
| B | Vicky | 17 |
| B | Emma | 20 |
| B | null | 3 |
| B | null | 65 |
+-------+----------+++-------+
This is the default behavior of the data step merge, except that it won't set the last row's variable to missing - but it's easy to fudge.
There are other ways to do this, the best in my opinion being the hash object if you're comfortable with that.
data names;
infile datalines dlm='|';
input ID $ NAME $;
datalines;
| A | Jack |
| A | Andy |
| A | Steve |
| A | Jay |
| B | Chris |
| B | Vicky |
| B | Emma |
;;;;
run;
data ages;
infile datalines dlm='|';
input id $ age;
datalines;
| A | 22 |
| A | 31 |
| A | 11 |
| B | 40 |
| B | 17 |
| B | 20 |
| B | 3 |
| B | 65 |
;;;;
run;
data want;
merge names(in=_a) ages(in=_b);
by id;
if _a;
if name ne lag(name) then output; *this assumes `name` is unique in id - if it is not we may have to do a bit more work here;
call missing(age); *clear age after output so we do not attempt to fill extra rows with the same age - age will be 'retain'ed;
run;

SQL compare multiple rows or partitions to find matches

The database I'm working on is DB2 and I have a problem similar to the following scenario:
Table Structure
-------------------------------
| Teacher Seating Arrangement |
-------------------------------
| PK | seat_argmt_id |
| | teacher_id |
-------------------------------
-----------------------------
| Seating Arrangement |
-----------------------------
|PK FK | seat_argmt_id |
|PK | Row_num |
|PK | seat_num |
|PK | child_name |
-----------------------------
Table Data
------------------------------
| Teacher Seating Arrangement|
------------------------------
| seat_argmt_id | teacher_id |
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 2 |
------------------------------
---------------------------------------------------
| Seating Arrangement |
---------------------------------------------------
| seat_argmt_id | row_num | seat_num | child_name |
| 1 | 1 | 1 | Abe |
| 1 | 1 | 2 | Bob |
| 1 | 1 | 3 | Cat |
| | | | |
| 2 | 1 | 1 | Abe |
| 2 | 1 | 2 | Bob |
| 2 | 1 | 3 | Cat |
| | | | |
| 3 | 1 | 1 | Abe |
| 3 | 1 | 2 | Cat |
| 3 | 1 | 3 | Bob |
| | | | |
| 4 | 1 | 1 | Abe |
| 4 | 1 | 2 | Bob |
| 4 | 1 | 3 | Cat |
| 4 | 2 | 2 | Dan |
---------------------------------------------------
I want to see where there are duplicate seating arrangements for a teacher. And by duplicates I mean where the row_num, seat_num, and child_name are the same among different seat_argmt_id for one teacher_id. So with the data provided above, only seat id 1 and 2 are what I would want to pull back, as they are duplicates on everything but the seat id. If all the children on the 2nd table are exact (sans the primary & foreign key, which is seat_argmt_id in this case), I want to see that.
My initial thought was to do a count(*) group by row#, seat#, and child. Everything with a count of > 1 would mean it's a dupe and = 1 would mean it's unique. That logic only works if you are comparing single rows though. I need to compare multiple rows. I cannot figure out a way to do it via SQL. The solution I have involves going outside of SQL and works (probably). I'm just wondering if there is a way to do it in DB2.
Does this do what you want?
select d.teacher_id, sa.row_num, sa.seat_num, sa.child_name
from seatingarrangement sa join
data d
on sa.seat_argmt_id = d.seat_argmt_id
group by d.teacher_id, sa.row_num, sa.seat_num, sa.child_name
having count(*) > 1;
EDIT:
If you want to find two arrangements that are the same:
select sa1.seat_argmt_id, sa2.seat_argmt_id
from seatingarrangement sa1 join
seatingarrangement sa2
on sa1.seat_argmt_id < sa2.seat_argmt_id and
sa1.row_num = sa2.row_num and
sa1.seat_num = sa2.seat_num and
sa1.child_name = sa2.child_name
group by sa1.seat_argmt_id, sa2.seat_argmt_id
having count(*) = (select count(*) from seatingarrangement sa where sa.seat_argmt_id = sa1.seat_argmt_id) and
count(*) = (select count(*) from seatingarrangement sa where sa.seat_argmt_id = sa2.seat_argmt_id);
This finds the matches between two arrangements and then verifies that the counts are correct.

Turn Parts of Rows into a Separate Column in SQL Server

I'm not sure if Pivot is the way to go with this, but I am looking to take part of a row and create a new column with it.
This is my example:
+--------+------------+--------+
| Person | PetName | PetAge |
+--------+------------+--------+
| 1 | Apple | 2 |
| 1 | Banana | 6 |
| 1 | Grapefruit | 3 |
| 2 | Red | 53 |
| 2 | Blue | 8 |
+--------+------------+--------+
This is my result/goal:
+--------+---------+--------+---------+--------+------------+--------+
| Person | PetName | PetAge | PetName | PetAge | PetName | PetAge |
+--------+---------+--------+---------+--------+------------+--------+
| 1 | Apple | 2 | Banana | 6 | Grapefruit | 3 |
| 2 | Red | 53 | Blue | 8 | | |
+--------+---------+--------+---------+--------+------------+--------+
How can I get the result from my example?
UPDATE: I just noticed that your table just had the Person in the first row.
I've done something similar. What I did was add a RowNumber per pet by person (OVER PARTITION BY PERSON) to the data. This will allow the data to be broken up and an order of numbers for each pet per person.
Make your normal table with just the PetName and PetAge.
Add a Tablix with just one column and row and put the previous table in it.
For the Column grouping, use ROW_NUM. For Row use Person.