T-SQL One column in multiple columns select query - tsql

I have a simple problem that I have not been able to find a solution to and I'm hoping someone on StackOverflow can help.
I currently have an example query as shown below
SELECT ID
, ColumnName
FROM Table
If I run this query I get the following result:
==================
ID | ColumnName
------------------
1 | One_Two_Three
2 | Four_Five_Six
==================
The result I'm after is as follows:
========================
ID | Col1 | Col2 | Col3
------------------------
1 | One | Two | Three
2 | Four | Five | Six
========================
Your assistence is appreciated.

Have a look at this example
DECLARE #Table1 TABLE
([ID] int, [ColumnName] varchar(13))
INSERT INTO #Table1
([ID], [ColumnName])
VALUES
(1, 'One_Two_Three'),
(2, 'Four_Five_Six')
;WITH Vals AS (
SELECT *,
CAST('<d>' + REPLACE([ColumnName], '_', '</d><d>') + '</d>' AS XML) ColumnValue
FROM #Table1
)
SELECT v.*,
A.B.value('.', 'varchar(max)')
FROM Vals v CROSS APPLY
ColumnValue.nodes('/d') A(B)
SQL Fiddle DEMO

Related

PostgreSQL UNNEST Array and Insert Into New Table

I have an array column I want to unnest, split the element values, and copy into another table. For example:
id | col1
-----------------
1 | '{"a:1", "b:2"}'
I'd like to insert into a new table that looks like:
table1_id | col1 | col2
------------------------
1 | 'a' | 1
1 | 'b' | 2
You can issue an insert from this select:
select id as table1_id,
(string_to_array(ary, ':'))[1] as col1,
(string_to_array(ary, ':'))[2] as col2
from table1
cross join lateral unnest(col1) as u(ary);
db<>fiddle here

Merging rows on SSRS

My raw data returned to SSRS.
IF OBJECT_ID('tempdb..#tmpElections') IS NOT NULL
DROP TABLE #tmpElections
create table #tmpElections
(
ClientId int,
MaterialType varchar(50),
QtyReq int,
QtySent int
)
insert into #tmpElections values (1,'MM1',100,50)
insert into #tmpElections values (2,'MM2',200,50)
insert into #tmpElections values (2,'MM2',200,25)
insert into #tmpElections values (3,'MM3',300,50)
insert into #tmpElections values (3,'MM3',300,150)
insert into #tmpElections values (3,'MM3',300,100)
insert into #tmpElections values (4,'MM4',400,300)
insert into #tmpElections values (4,'MM4',400,100)
select * from #tmpElections
On the report, status = partial, if QtySent < QtyReq, else full.
My ssrs report should display as below, merging/blanking the row cells,
having same Clientid,materialType and status = 'Full'.The column QtySent should be displayed.
Desired Report Sample
Whats the best approach and how to achieve this result.
Should this be handled at T-SQL or SSRS.
The yellow highlighted cells should be blank on the report within each group.
Sample Report
I'd use a sub-query to total up your QtySent for comparison, together with a CASE to assign the status text value. The rest is just SSRS formatting.
SELECT
e.*
,CASE
WHEN s.TotSent = e.QtyReq THEN 'Full'
ELSE 'Partial'
END AS [Status]
FROM
#tmpElections AS e
LEFT JOIN
(
SELECT
e2.ClientId
,e2.MaterialType
,SUM(e2.QtySent) AS TotSent
FROM
#tmpElections AS e2
GROUP BY
e2.ClientId
,e2.MaterialType
) AS s
ON
s.ClientId = e.ClientId
AND s.MaterialType = e.MaterialType;
Result set:
+----------+--------------+--------+---------+---------+
| ClientId | MaterialType | QtyReq | QtySent | Status |
+----------+--------------+--------+---------+---------+
| 1 | MM1 | 100 | 50 | Partial |
| 2 | MM2 | 200 | 50 | Partial |
| 2 | MM2 | 200 | 25 | Partial |
| 3 | MM3 | 300 | 50 | Full |
| 3 | MM3 | 300 | 150 | Full |
| 3 | MM3 | 300 | 100 | Full |
| 4 | MM4 | 400 | 300 | Full |
| 4 | MM4 | 400 | 100 | Full |
+----------+--------------+--------+---------+---------+
You are almost there.. what I would do is add a case statement to determine the status :
select ClientId,MaterialType, max(QtyReq) as qtyreq, sum(QtySent) as qtysent
, case when sum(QtySent)<max(QtyReq) then 'Partial' else 'Full' end as [status]
from #tmpElections
group by
ClientId
,MaterialType
Then in your report.. you just group on the first three columns that is shown in your image description... and then the rest as details
Thank you all for your comments and solutions. I was able to solve my problem as below.
Create procedure dbo.TestRptSample
as
begin
create table #tmpElections
(
ClientId int,
MaterialType varchar(50),
QtyReq int,
QtySent int,
SentDate datetime
)
insert into #tmpElections values (1,'MM1',100,50,'02/01/2018')
insert into #tmpElections values (2,'MM2',200,50,'02/01/2018')
insert into #tmpElections values (2,'MM2',200,25,'03/01/2018')
insert into #tmpElections values (3,'MM3',300,50,'02/01/2018')
insert into #tmpElections values (3,'MM3',300,150,'02/15/2018')
insert into #tmpElections values (3,'MM3',300,100,'03/01/2018')
insert into #tmpElections values (4,'MM4',400,300,'02/01/2018')
insert into #tmpElections values (4,'MM4',400,100,'03/01/2018')
create table #tmpFinal
(
ClientId int,
MaterialType varchar(50),
QtyReq int,
QtySent int,
SentDate datetime,
mStatus varchar(100),
)
Insert into #tmpFinal
select b.*,a.status
from
(
select ClientId,MaterialType, max(QtyReq) as qtyreq, sum(QtySent) as qtysent
, case when sum(QtySent)<max(QtyReq) then 'Partial' else 'Full' end as [status]
from #tmpElections
group by
ClientId
,MaterialType
) A
inner join #tmpElections B on a.ClientId = b.ClientId and a.MaterialType = b.MaterialType;
with x as
(
select *,
ROW_NUMBER() over (partition by clientId,materialType,qtyReq
order by sentdate) as Rowno
from #tmpFinal
)
select *
,max(rowno) over (partition by clientId,materialType,qtyReq) as MaxRow
from x
order by clientId ,sentdate
end
Used the procedure with row_number to generate row numbers within the group by sets.
On the report, in visibility expressions of the row text boxes, used the following expression to show or hide that column.
iif(Fields!mStatus.Value="Full" and Fields!Rowno.Value <> Fields!MaxRow.Value ,True,False)

PostgreSQL mass insert into a table?

I need to mass insert all the values from col_a into another table. I can do it one at a time like this:
INSERT INTO table_2 (col_a_id)
SELECT 'col_a_id'
FROM table_1
WHERE col_a = 'x';
But is there a way I can just insert all the columns?
EDIT
Lets say I have this table:
Col_a | Col_b |
------------------------
1 | a |
2 | b |
3 | c |
Instead of checking what is in col_a can I just insert each instance of col_a into a table? so I'll have 1, 2 & 3 in table_2?
INSERT INTO table_2 (col1, col2, col3, .... , coln)
SELECT col1, col2, col3, .... , coln
FROM table_1
WHERE col_a = 'x';
Note: String are separated by single quote
SELECT 'this is a string'
Fieldname use double quote:
SELECT "myFieldName", "col1"
EDIT:
If you want check all columns for 'x'
WHERE 'x' IN (col1, col2, col3, .... , coln)

How to compare two identicals tables data of each column in postgres?

I want compare two table's all column values.The two table is identical tables means column number is same and primary key is same. can any one suggest query which compare such two tables in postgres.
The query should give the column name and what is the two different value of two tables.Like this
pkey | column_name | table1_value | table2_value
123 | bonus | 1 | 0
To get all different rows you can use:
select *
from table_1 t1
join table_2 t2 on t1.pkey = t2.pkey
where t1 is distinct from t2;
This will only compare rows that exist in both tables. If you also want to find those that are missing in on of them use a full outer join:
select coalesce(t1.pkey, t2.pkey) as pkey,
case
when t1.pkey is null then 'Missing in table_1'
when t2.pkey is null then 'Missing in table_2'
else 'At least one column is different'
end as status,
*
from table_1 t1
full ojoin table_2 t2 on t1.pkey = t2.pkey
where (t1 is distinct from t2)
or (t1.pkey is null)
or (t2.pkey is null);
If you install the hstore extension, you can view the differences as a key/value map:
select coalesce(t1.pkey, t2.pkey) as pkey,
case
when t1.pkey is null then 'Missing in table_1'
when t2.pkey is null then 'Missing in table_2'
else 'At least one column is different'
end as status,
hstore(t1) - hstore(t2) as values_in_table_1,
hstore(t2) - hstore(t1) as values_in_table_2
from table_1 t1
full ojoin table_2 t2 on t1.pkey = t2.pkey
where (t1 is distinct from t2)
or (t1.pkey is null)
or (t2.pkey is null);
Using this sample data:
create table table_1 (pkey integer primary key, col_1 text, col_2 int);
insert into table_1 (pkey, col_1, col_2)
values (1, 'a', 1), (2, 'b', 2), (3, 'c', 3), (5, 'e', 42);
create table table_2 (pkey integer primary key, col_1 text, col_2 int);
insert into table_2 (pkey, col_1, col_2)
values (1,'a', 1), (2, 'x', 2), (3, 'c', 33), (4, 'd', 52);
A possible result would be:
pkey | status | values_in_table_1 | values_in_table_2
-----+----------------------------------+-------------------+------------------
2 | At least one column is different | "col_1"=>"b" | "col_1"=>"x"
3 | At least one column is different | "col_2"=>"3" | "col_2"=>"33"
4 | Missing in table_1 | |
5 | Missing in table_2 | |
Example data:
create table test1(pkey serial primary key, str text, val int);
insert into test1 (str, val) values ('a', 1), ('b', 2), ('c', 3);
create table test2(pkey serial primary key, str text, val int);
insert into test2 (str, val) values ('a', 1), ('x', 2), ('c', 33);
This simple query gives a complete information on differences of two tables (including rows missing in one of them):
(select 1 t, * from test1
except
select 1 t, * from test2)
union all
(select 2 t, * from test2
except
select 2 t, * from test1)
order by pkey, t;
t | pkey | str | val
---+------+-----+-----
1 | 2 | b | 2
2 | 2 | x | 2
1 | 3 | c | 3
2 | 3 | c | 33
(4 rows)
In Postgres 9.5+ you can transpose the result to the expected format using jsonb functions:
select pkey, key as column, val[1] as value_1, val[2] as value_2
from (
select pkey, key, array_agg(value order by t) val
from (
select t, pkey, key, value
from (
(select 1 t, * from test1
except
select 1 t, * from test2)
union all
(select 2 t, * from test2
except
select 2 t, * from test1)
) s,
lateral jsonb_each_text(to_jsonb(s))
group by 1, 2, 3, 4
) s
group by 1, 2
) s
where key <> 't' and val[1] <> val[2]
order by pkey;
pkey | column | value_1 | value_2
------+--------+---------+---------
2 | str | b | x
3 | val | 3 | 33
(2 rows)
I tried all of the above answer.Thanks guys for your help.Bot after googling I found a simple query.
SELECT <common_column_list> from table1
EXCEPT
SELECT <common_column_list> from table2.
It shows all the row of table1 if any table1 column value is different from table2 column value.
Not very nice but fun and it works :o)
Just replace public.mytable1 and public.mytable2 by correct tables and
update the " where table_schema='public' and table_name='mytable1'"
select * from (
select pkey,column_name,t1.col_value table1_value,t2.col_value table2_value from (
select pkey,generate_subscripts(t,1) ordinal_position,unnest(t) col_value from (
select pkey,
(
replace(regexp_replace( -- null fields
'{'||substring(a::character varying,'^.(.*).$') ||'}' -- {} instead of ()
,'([\{,])([,\}])','\1null\2','g'),',,',',null,')
)::TEXT[] t
from public.mytable1 a
) a) t1
left join (
select pkey,generate_subscripts(t,1) ordinal_position,unnest(t) col_value from (
select pkey,
(
replace(regexp_replace( -- null fields
'{'||substring(a::character varying,'^.(.*).$') ||'}' -- {} instead of ()
,'([\{,])([,\}])','\1null\2','g'),',,',',null,')
)::TEXT[] t
from public.mytable2 a
) a) t2 using (pkey,ordinal_position)
join (select * from information_schema.columns where table_schema='public' and table_name='mytable1') c using (ordinal_position)
) final where COALESCE(table1_value,'')!=COALESCE(table2_value,'')

Microsoft TSQL change text row to column

I want to change the 20 rows with one column to 1 row with 20 columns to insert it later in a second database
Name
----------
- Frank
- Dora
- ...
- Michael
to
Name1 | Name2 | ... | Name20
Frank | Dora | ... | Michael
I tried
SELECT *
FROM (SELECT TOP 20 firstname AS NAME
FROM database) AS d
PIVOT (Min(NAME)
FOR NAME IN (name1,
name2,
name3,
name4,
name5,
name6,
name7,
name8,
name9,
name10,
name11,
name12,
name13,
name14,
name15,
name16,
name18,
name19,
name20) ) AS f
But all names are NULL. DEMO
You were close... But your inner select must carry the new column name. Try it like this:
DECLARE #tbl TABLE(Name VARCHAR(100));
INSERT INTO #tbl VALUES('Frank'),('Dora'),('Michael');
SELECT p.*
FROM
(
SELECT 'Name' + CAST(ROW_NUMBER() OVER(ORDER BY Name) AS VARCHAR(150)) AS ColumnName
,Name
From #tbl
) AS tbl
PIVOT
(
MIN(Name) FOR ColumnName IN(Name1,Name2,Name3)
) AS p