bigquery - Combine row data with columns of unique data - sql

can this scenario be accomplished with a single query?
read example table and transpose based on id each cat and value.
Existing Table would contain the columns and or null columns are created when
select is done (e.gl NULL Att1_Val1)
Example Table Existing Table
id name cat value ID Name Att1_Val1 Att2_Val1 Att3_Val1 Att4_Val1
1 name1 att1 1 1 Name1 1 2 3 Null
1 name1 att2 2 1 Name2 4 5 6 7
1 name1 att3 3
2 name2 att1 4
2 name2 att2 5
2 name2 att3 6
2 name2 att4 7
See snapshot for a Better view of tables

I resolved this for my real table structure (names in the example where changed and I also had a case statement. But this is the basic of how I solved.
Select id, Name, Att1, Att2, Att3, Att4
FROM (SELECT id, value, att FROM 'List_table' as Source_Table)
PIVOT
(MAX(Value) FOR att
IN ('Att1', 'Att2', 'Att3','Att4'))
AS Pivot_table

Related

Condition filtering SQL

I have a table
Table name - commands
id
name
status
group_id
id - number
name - string
status - 0 or 1
group_id - number
I need to sort as follows: for all elements with the same group_id I have to check if at least one has a status of 1, if so, then leave, if not, then remove such a group and so on for all group_id
I tried to do it through GROUP BY, and then using HAVING to remove unnecessary groups, but this way I don't get the whole table to be displayed or a query that does not work.
I think it should look like:
SELECT COUNT(*) FROM commands GROUP BY group_id HAVING *condition*
Please let me know if there are any other commands to use.
id
name
status
group_id
1
name1
0
1
2
name2
0
1
3
name3
0
2
4
name4
1
2
5
name5
1
2
6
name6
0
3
7
name7
1
4
Result:
id
name
status
group_id
3
name3
0
2
4
name4
1
2
5
name5
1
2
7
name7
1
4
In Postgres, that's a good spot to use a boolean window function:
select *
from (
select t.*, bool_or(status = 1) over(partition by group_id) has_status_1
from mytable t
) t
where has_status_1
bool_or checks if any row in the group satisfies its predicate ; we can use this information for filtering.
The upside is that the table is scanned only once, as opposed to the correlated subquery solution.
You may use EXISTS operator with a correlated subquery as the following:
SELECT id, name, status, group_id
FROM table_name T
WHERE EXISTS(SELECT 1 FROM table_name D WHERE D.group_id = T.group_id AND D.status=1)
ORDER BY id
See a demo.

pivot/unpivot statement

Hi, having table like this
NR PROJECT RESULT
1 name1 234
1 name2 937
2 name1 3
2 name2 6
I'm trying to have results presented this way:
NR NAME1 NAME2
1 234 937
2 3 6
so the VALUES of the PROJECT column become headers presenting respective RES value while the same NR values are merged into a single row
help :)
If you're working with a fixed list of projects, you can use (as you've mention in the title of your question) a pivot.
http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html
SELECT
*
FROM
yourTable
PIVOT
(
SUM(result)
FOR project IN ('name1' AS NAME1, 'name2' AS NAME2)
)
This would give the same results as from a "conditional aggregate".
SELECT
NR,
SUM(CASE WHEN PROJECT = 'name1' THEN result END) AS NAME1,
SUM(CASE WHEN PROJECT = 'name2' THEN result END) AS NAME2
FROM
yourTable
GROUP BY
NR
Examples : http://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=19f31ce152f4f88c3d74e867016765d7

Select dynamic column based on value of another column?

Given the following table, I would like to dynamically select the Name1 or Name2 field based on the value of the WhichName column.
id Name1 Name2 WhichName SomeValue
1 Bob James 1 Blue
2 Steve 2 Horse
3 Fred 1 Radish
The results should look like this:
id Name SomeValue
1 Bob Blue
2 Steve Horse
3 Fred Radish
DBMS is Caché
You can do this with case:
select id,
(case when WhichName = 1 then Name1 else Name2 end) as Name,
SomeValue
from <table>;
Note: if your prefer Name1, unless it is NULL, then you can use COALESCE():
select id, coalesce(Name1, Name2) as Name, SomeValue
from <table>;

Optimize rows to columns conversion

I have a big Oracle table (around 40 million rows) that looks like this:
ID Name Question Answer Reason
3 Name1 1 Yes blah blah
3 Name1 2 No NA
3 Name1 3 No NA
3 Name1 4 Yes blah2
3 Name1 5 Yes null
3 Name1 6 Yes blah3
3 Name1 7 No null
6 Name2 1 Yes blah4444
6 Name2 2 No null
6 Name2 3 Yes blah3
6 Name2 4 NA blah5
6 Name2 5 Yes null
6 Name2 6 Yes blah6
6 Name2 7 NA null
I need one row per ID i.e. I will need to add columns for each question's answer (there are 7 questions per ID) and each question's reason. I need to make it look like this:
ID Name Q1 Q1-Reason Q2 Q2-Reason Q3 Q3-Reason etc.
3 Name1 Yes blah blah No null
6 Name2 Yes blah4444 No null
My query currently looks like this:
select
A.ID,A.NAME,B1.Q1,B1.Q1-REASON,B2.Q2,B2.Q2-REASON
from
TABLENAME A
inner join
(
select distinct C1.ID,C1.ANSWER as Q1,C1.REASON as Q1-REASON
from TABLENAME C1
where C1.QUESTION=1
) B1 on B1.ID=A.ID
inner join
(
select distinct C2.ID,C2.ANSWER as Q2,C2.REASON as Q2-REASON
from TABLENAME C2
where C2.QUESTION=2
) B2 on B2.ID=A.ID
...
...
However, as the table is huge, this is taking a VERY long time to retrieve the data. Could someone suggest ways to optimize this query?
I'm on Oracle 10g and SQLDeveloper 4.0.2.15
You could do this:
SELECT
TABLENAME.ID,
TABLENAME.Name,
MAX(CASE WHEN TABLENAME.Question=1 THEN TABLENAME.Answer ELSE NULL END) AS Q1,
MAX(CASE WHEN TABLENAME.Question=1 THEN TABLENAME.Reason ELSE NULL END) AS Q1_Reason,
MAX(CASE WHEN TABLENAME.Question=2 THEN TABLENAME.Answer ELSE NULL END) AS Q2,
MAX(CASE WHEN TABLENAME.Question=2 THEN TABLENAME.Reason ELSE NULL END) AS Q2_Reason,
MAX(CASE WHEN TABLENAME.Question=3 THEN TABLENAME.Answer ELSE NULL END) AS Q3,
MAX(CASE WHEN TABLENAME.Question=3 THEN TABLENAME.Reason ELSE NULL END) AS Q3_Reason
/*And so on*/
FROM
TABLENAME
GROUP BY
TABLENAME.ID,
TABLENAME.Name

Taking only 1 row from a group of rows sharing the same field value

I have a SQL Server 2008 database with records like the following
001 CAT 1 2 3
002 DOG 3 3 1
003 DOG 2 1 1
004 DOG 2 1 3
005 CAT 1 3 4
I want to take 1 row for each unique value in column 2 (cat and dog)
so this would get me (one possible answer):
001 CAT 1 2 3
002 DOG 3 3 1
Column 1 is the PK and is a string.
Column 2 is a string
Columns 3-5 are just there to indicate there are other variable fields which I need in the final result.
SELECT t1.*
FROM YourTable t1
JOIN
(SELECT MIN(Col1) AS FirstId
FROM YourTable GROUP BY Col2) x ON t1.Col1 = x.FirstId
SELECT pk, DISTINCT pet, col3, col4, col5 FROM myPetsTable
Would that work? Taking a shot in the dark here :)