Combining data from 2 tables and pivoting data from 1 of them - sql

I have the current situation:
TableA
----------
SN Date OpsID
1234 2018-02-12 1
1324 2018-02-12 2
2134 2018-02-13 3
TableB
----------
Name String Number OpsID
Value1 Hello NULL 1
Value2 NULL 1111 1
Value3 Apples NULL 1
Value1 There NULL 2
Value2 NULL 2222 2
Value3 Pears NULL 2
Value1 Baby NULL 3
Value2 NULL 3333 3
Value3 Bananas NULL 3
...and the result I'm looking for is:
SN Date Value1 Value2 Value3
1234 2018-02-12 Hello 1111 Apples
1324 2018-02-12 There 2222 Pears
2134 2018-02-13 Baby 3333 Bananas
The query I ran is obviously wrong because I'm getting mostly NULL and only Value data, but here it is anyway:
SELECT SN,Date,Value1,Value2,Value3
FROM(
SELECT TableA.SN,
TableA.Date,
TableB.Name,
TableB.String,
TableB.Number
FROM TableA,TableB
WHERE
TableA.OpsID = TableB.OpsID
ORDER BY Date ASC
)Temp
PIVOT(
MAX(Value)
FOR Name in(
Value1,Value2,Value3
)
)PIV
Note that Value1 and Value3 are always VARCHAR and Value2 is always an INT

You combine String and Number into a single column in a subquery, and then pivot the values back out into their own columns like this:
SELECT SN, Date, Value1, CAST(Value2 AS INT) Value2, Value3
FROM
(
SELECT a.SN, a.Date, B.Name, ISNULL(b.String, CAST(b.Number AS VARCHAR(10))) Value
FROM TableA A
INNER JOIN TableB B ON A.OpsID = B.OpsID
)sq1
PIVOT (MAX(Value) FOR Name IN ([Value1], [Value2], [Value3]))sq2

You can do conditional aggregation :
select a.SN, a.date,
max(case when b.Name = 'Value1' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value1,
max(case when b.Name = 'Value2' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value2,
max(case when b.Name = 'Value3' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value3
from tablea a inner join
tableb b
on b.OpsID = a.OpsID
group by a.SN, a.date;

Related

SQL PIVOT not as suspected

I'm working on a data extraction of multiple tables for so far i have this
Table A
ID
value
1
123
Table B
ID
FileID
FieldID
A_ID
Data
1
1
1
1
abc
2
1
2
1
123
3
1
3
1
TRUE
4
1
1
2
def
5
1
2
2
456
6
1
3
2
FALSE
so far I have
SELECT Id, Plate, [1] as field1, [2] as field2, [3] as field3 FROM
(SELECT A.Id, A.value , B.Data as datavalue, B.Id as dataid
FROM TableA A, TableB B
WHERE A.Id = B.A_ID)as P
PIVOT (MAX(dataid) FOR datavalue in ([1],[2],[3])) as PVT
the answer I expect
Id
Value
Field1
Field2
Field3
1
123
abc
123
TRUE
the answer I get
Id
Value
Field1
Field2
Field3
1
123
NULL
NULL
NULL
what am i missing
can't get it figured out
You need to LEFT JOIN from:
Table B to Table A
instead of
Table A to Table B
Switch the two tables around within the nested select.
Use Group by and Max function and change pivot code to :
PIVOT (MAX(datavalue) FOR datavalue in ([abc],[123],[TRUE])) AS PVT
SELECT Id,
value,
max([abc]) as field1,
max([123]) as field2,
max([TRUE]) as field3
FROM
(SELECT A.Id, A.value , B.Data AS datavalue, B.Id AS dataid
FROM TableA A, TableB B
WHERE A.Id = B.A_ID) AS P
PIVOT (MAX(datavalue) FOR datavalue in ([abc],[123],[TRUE])) AS PVT
GROUP BY id,value
Demo in db<>fiddle
I believe you meant B.FieldId instead of B.Id. Other than that you need slight modification (you got the dataId and dataValue wrong, it would be
... Max(datavalue) for dataId in ...
instead of
... Max(dataId) for dataValue in ...
Here is revised version:
SELECT
ID, PVT.value, [1] AS field1, [2] AS field2, [3] AS field3
FROM
(
SELECT
A.ID, A.value, B.Data AS datavalue, B.FieldId AS dataid
FROM TableA A
INNER JOIN TableB B ON A.ID=B.A_ID
) AS P
PIVOT(MAX(datavalue)
FOR dataid IN([1], [2], [3])
) AS PVT;
Here is DBFiddle demo.

SQL server query: only certain column values into row, iterating

I need to build a SQL query in SQL SERVER 10.50.1600.1. I have the following model situation:
id1 | value1
id1 | value2
id2 | value1
id3 | value1
id3 | value2
...
and would like to end up in a situation as
id1 | value1 | value2
id2 | value1 | null
id3 | value1 | value2
...
I only know that for each id[n] there are at most 4 values recorded.
EDIT: I know there are at most 4 values for each, but they could be anything. They can be any number included in [0, 9000] or a string (about 10 possibilities). My bad, I didn't explain well.
If you know the values in advance, and the values are unique per ID (as they seem to be from your question statement) it's fairly straightforward:
-- Setup
declare #a table (id nvarchar(50), value nvarchar(50))
insert #a(id, value) values
('id1', 'value1'),
('id1', 'value2'),
('id2', 'value1'),
('id3', 'value1'),
('id3', 'value2')
;
SELECT id,
MAX(CASE value WHEN 'value1' THEN value END) AS value1,
MAX(CASE value WHEN 'value2' THEN value END) AS value2,
MAX(CASE value WHEN 'value3' THEN value END) AS value3,
MAX(CASE value WHEN 'value4' THEN value END) AS value4
FROM #a
GROUP BY id
Below query will help you :-
declare #test table (id nvarchar(50), value nvarchar(50))
insert #test(id, value) values
('id1', 'value1'),
('id1', 'value2'),
('id1', 'value3'),
('id1', 'value4'),
('id2', 'value1'),
('id3', 'value1'),
('id3', 'value2'),
('id3', 'value3');
select ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) AS ROWNUM,id,value into #t1 from #test
SELECT distinct id,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=1) AS Value1,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=2) AS Value2,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=3) AS Value3,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=4) AS Value4
FROM #t1 a
drop table #t1
Output :-
id Value1 Value2 Value3 Value4
id1 value1 value2 value3 value4
id2 value1 NULL NULL NULL
id3 value1 value2 value3 NULL
Assumtion: TABLE: table_name(id_column, value_column). With each value of id_column there are at most 4 values of value_column
Then you could use this
WITH tmp as
(SELECT
*
,ROW_NUMBER() over (PARTITION BY id_column order by value_column) rwn
FROM
table_name
)
SELECT
id_column
,MAX(CASE WHEN rwn = 1 THEN value_column END) value1
,MAX(CASE WHEN rwn = 2 THEN value_column END) value2
,MAX(CASE WHEN rwn = 3 THEN value_column END) value3
,MAX(CASE WHEN rwn = 4 THEN value_column END) value4
FROM
tmp
GROUP BY
id_column;

Horizontal to Vertical View SQL

I have the following table:
oDate value1 value2 value3 value4
2014-06-01 10 20 30 40
2014-06-02 20 25 35 50
I want to have the following result
oDate oField oValue
2014-06-01 Value1 10
2014-06-01 Value2 20
2014-06-01 Value3 30
2014-06-01 Value4 40
Is it possible to do that in SQL?
Need advice. Cheers,
You could do this:
Test data:
DECLARE #tbl TABLE(oDate DATETIME,value1 INT,value2 INT,value3 INT,value4 INT)
INSERT INTO #tbl
VALUES
('2014-06-01',10,20,30,40),
('2014-06-02',20,25,35,50)
UNPIVOT query
SELECT
*
FROM
(
SELECT
oDate,
value1,
value2,
value3,
value4
FROM
#tbl
) sourceTable
UNPIVOT
(
oField FOR oValue IN
(value1,value2,value3,value4)
) AS unpvt
Reference:
Using PIVOT and UNPIVOT
Try this
SELECT DISTINCT ODATE,VALUE,FIELD
FROM
(SELECT odate,value1,value2,value3,value4
FROM #temp) p
UNPIVOT
(VALUE FOR FIELD IN
(value1,value2,value3,value4)
)AS unpvt;
GO
How about this?
select
oDate,
'Value1' as oField,
value1 as oValue
from yourTable
union all
select
oDate,
'Value2' as oField,
value2 as oValue
from yourTable
union all
select
oDate,
'Value3' as oField,
value3 as oValue
from yourTable
union all
select
oDate,
'Value4' as oField,
value4 as oValue
from yourTable
order by oDate, oField

Return null row on select sql

I know this might seem a bit strange but I want to build a stored procedure that returns some values but I want the first row to be a null value. What I have for the query and returns are
SELECT CONCAT(id, ' ', item)As DisplayBox, id, item FROM table
DisplayBox id expense
1 Value2 1 Value2
2 Value3 2 Value3
3 Value4 3 Value4
4 Value5 4 Value5
But I am interested in having a result like
DisplayBox id Item
<BlankText> Null <BlankText>
1 Value2 1 Value2
2 Value3 2 Value3
3 Value4 3 Value4
4 Value5 4 Value5
You can use UNION ALL:
SELECT NULL AS DisplayBox, NULL AS id, NULL AS item
UNION ALL
SELECT CONCAT(id, ' ', item)As DisplayBox, id, item FROM table
SELECT null as displaybox, null as id, null as item from dual
union all
SELECT CONCAT(id, ' ', item)As DisplayBox, id, item FROM table
order by (case when id is null then 0 else 1 end)

How to count the column

Table1' Sample data:
ID value1 Value2 value3
001 10 20 30
002 20 10 null
003 10 null null
004 10 null 30
....
From the table1, I want to make a coulmn count.
Count of row query
Select count(*) from table1 'It will give only row count.
But i need column count, which column value should not be null
Expected output
ID | totcolumn
-----------------
001 3
002 2
003 1
004 2
....
How to make a query, need query help
Use SUM as follows:
SELECT id,
SUM(CASE WHEN value1 IS NULL then 0 ELSE 1 END) +
SUM(CASE WHEN value2 IS NULL then 0 ELSE 1 END) +
SUM(CASE WHEN value3 IS NULL then 0 ELSE 1 END) AS 'COUNT'
FROM table1
group by id
DEMO
This is a nice opportunity to use UNPIVOT if you are on MS SQL Server 2005 or later. First set up some sample data:
create table ColumnCount (
ID char(3) not null,
Value1 int,
Value2 int,
Value3 int
)
insert into ColumnCount(ID,Value1,Value2,Value3)
select '001',10,20,30
union all select '002',20,10,null
union all select '003',10,null,null
union all select '004',10,null,30
union all select '005',null,null,null
I added 005 to the sample data you provided above, to show how to handle the case where all ValueX columns are null.
UNPIVOT "normalizes" the data for you so that you can use COUNT against the rows:
select *
from ColumnCount
unpivot (Value for ValueN in (Value1, Value2, Value3)) as upvt
ID Value ValueN
001 10 Value1
001 20 Value2
001 30 Value3
002 20 Value1
002 10 Value2
003 10 Value1
004 10 Value1
004 30 Value3
Notice that it eliminated the NULL values already, so you do not have to. Unfortunately this means that rows with NULL in all ValueX columns (e.g., ID='005') will not show up if you do a simple count. Instead, gather all ID's in a subquery or CTE like AllIds below:
with ColumnsOnRows as (
select *
from ColumnCount
unpivot (Value for ValueN in (Value1, Value2, Value3)) as upvt
),
AllIds as (
select distinct ID
from ColumnCount
)
select AllIds.ID, count(distinct Value) as totcolumn
from AllIds
left outer join ColumnsOnRows
on ColumnsOnRows.ID = AllIds.ID
group by AllIds.ID
Result:
ID totcolumn
001 3
002 2
003 1
004 2
005 0
If I understand you correctly what you need is something like this
SELECT ISNULL(Value1, 0) + ISNULL(Value2, 0) + ISNULL(Value3, 0) AS _Sum FROM table1
ISNULL will replace the value with 0 if it is NULL