much like this original SO Pivoting rows into columns dynamically in Oracle
but i would like to do the opposite
how can i get
ID NAME AGE GENDER STATUS
---- ----- ----- ------ --------
1 Bob 30 male
2 Susan married
into this
ID K V
---- ----- -----
1 name Bob
1 age 30
1 gender male
2 name Susan
2 status married
You are looking for unpivot.
select * from t
unpivot (
v for k in ("NAME","AGE","GENDER","STATUS")
) u
You may have a type mismatch if the age column is an integer. In that case convert it to a character before unpivoting.
select *
from (select id,name,to_char(age) age,gender,status from t) t
unpivot (
v for k in ("NAME","AGE","GENDER","STATUS")
) u
Related
I have a table like:
id name value
--------------------
1 x 100
1 y 200
1 z 300
2 x 10
2 y abc
2 z 001
3 x 1
...
--------------------
and I need to transform it into something like that:
id x y z
---------------------
1 100 200 300
2 10 abc 001
3 1 ...
---------------------
Names are determined. I could make multiple joins but I'm looking for a more elegant solution.
Use conditional aggregation which in Postgres uses the filter syntax:
select id,
max(value) filter (where name = 'x') as x,
max(value) filter (where name = 'y') as y,
max(value) filter (where name = 'z') as z
from t
group by id;
The additional module tablefunc provides variants of the crosstab() function, which is typically fastest:
SELECT *
FROM crosstab(
'SELECT id, name, value
FROM tbl
ORDER BY 1, 2'
) AS ct (id int, x text, y text, z text);
You seem to have a mix of numbers and strings in your value, so I chose text as output.
See:
PostgreSQL Crosstab Query
I have oracle11 table like this:
id name have_child
----------- ---------- ------------
1 Alison N
2 Mary N
3 Meg Y
4 Mary N
5 Meg N
where have_child is probably Boolean = Y/N.
I want to do query to list wrong behavior where one name can be Y and N - like Meg:
id name have_child
----------- ---------- ------------
3 Meg Y
5 Meg N
As a result I want to list entire rows.
I do not want to list proper duplicates - like Mary:
id name have_child
----------- ---------- ------------
2 Mary N
4 Mary N
I know how to count particular names and list what names appears more than 1 time like this:
SELECT name from table
GROUP BY name
HAVING COUNT(*)>1;
This could be a way:
select id, name, have_child
from (
select t.*,
count(distinct have_child) over (partition by name) as num
from yourTable t
)
where num > 1
The inner query simply lists all the records of the table, adding a column which gives the number of different values of have_child for the same name.
The external one simply filters for rows in which this number is greater than 1.
Basically I need to generate a frequency table using sql, and I have a sample table like this:
user_id user_label code1 date
------ ----------- ----- ------
1 x a 01-01
1 x a 01-01
1 x a 01-02
1 x b 01-01
1 x c 01-02
1 y a 01-01
2 x a 01-01
etc
The rule to count occurrences is if two rows have the same user_id ,user_label and date ,then repeated codes should only be counted once.
For example, for the first two rows the frequency table should be :
user_id user_label code1 count_code_1
-------- ----------- ----- ------------
1 x a 1
Because even though there are two instances of a, but they happen on the same date so should only be counted once and I need do this for every unique codes in code_1 column
for all combinations of user_id + user_label
After processing the third row , the frequency table should be :
user_id user_label code_1 count_code_1
-------- ----------- ------ ------------
1 x a 2
Since although is the same code ('a') but it happens on a different date (01-02)
In the end, for the sample table given above, the desired result should be
user_id user_label code_1 count_code_1
-------- ----------- ------ -------------
1 x a 2
1 x b 1
1 x c 1
1 y a 1
2 x a 1
What I have so far is
select t.user_id, t.user_label, t.code_1, count(###)
from t
group by t.code_1,t.user_id, t.user_label
The problem is
1. I don't know what to put inside the count 2. I don't know how to incorporate the condition on date in to this query.
Any suggestion, correction would be greatly appreciated.
You seem to want count(distinct date):
select t.user_id, t.user_label, t.code_1,
count(distinct date)
from t
group by t.code_1,t.user_id, t.user_label
I have two tables:
table 1:
ID name
--------- -----------
1 john
2 salma
3 tony
table2:
ID Tasks amount
--------- ----------- ----------
1 write 2
1 memorize 3
1 read 6
1 sing NULL
2 write 1
2 memorize NULL
2 read 5
2 sing NULL
3 write NULL
3 memorize 8
3 read 2
3 sing NULL
I want to insert new columns in table1 for each task mentioned in table2.
Table1:
ID name write memorize read sing
--------- ----------- -------- --------- ------- --------
1 john 2 3 6 NULL
2 salma 1 NULL 5 NULL
3 tony NULL 8 2 NULL
I can do the insert in Table1 for one ID at a time, but not for all of them. Thanks in advance!
First, I inserted the row values in a temporary table as columns using pivot:
select * into #Results
from
(
select ID,Tasks,amount
from #Table2
) tb2
pivot
(
max(amount)
for ID in ([1], [2], [3])
) as piv
Then, I did an inner join with Table1:
select * from Table1 tb1 inner join #Results r on r.ID =tb1.ID
Thanks #JamesL for the seggustion to use pivot!
There is a column that exists in 2 tables. In table 1, this column contains values in binary form (int), 1 and 0, while the other table contains the column in form 'Y' and 'N'.
Essentially I need to display rows in table 1 that contain values that are different from values in table 2 for that column. How do I compute 1 to Y and 0 to N for comparison?
Example:
Table 1:
DateRecorded SchoolName StudentName isAbsent hasPassed
------------ ---------- ----------- -------- ---------
2011-04-03 ABC John Y Y
2011-04-05 ABC John N Y
Table 2:
DateRecorded SchoolName StudentName isAbsent hasPassed
------------ ---------- ----------- -------- ---------
2011-04-03 ABC John 0 1
2011-04-05 ABC John 0 1
Should return row:
2011-04-03 ABC John Y Y
from Table 1 as this row is conflicting with the same row in Table 2.
Try this:
SELECT * FROM tbl1
EXCEPT
SELECT
daterecorded,
schoolname,
studentname,
CASE isAbsent WHEN 1 THEN 'Y' WHEN 0 THEN 'N' END AS isAbsent,
CASE hasPassed WHEN 1 THEN 'Y' WHEN 0 THEN 'N' END AS hasPassed
FROM tbl2
SQL-Fiddle Demo