TSQL challenge to join and union in one step, is it pssble? - tsql

I'm trying to make single datasource which will have several data types which later will be ID'ed in our BI application (and I can NOT change anything), each type ID'ed by column Type like in example below, so basically I have 2 tables which I want join/union at the same time, I tried to play with join, and could not make it work so fare. Do you think it's doable ?? THere is some dynamic going on in input tables so it's hard to go with preset columns which will serve all tables.
This is my input:
;WITH cte1 AS (SELECT 'A' type, 'alpha1' rec1, 'bravo1' rec2 UNION
SELECT 'A' type, 'alpha2' rec1, 'bravo2' rec2 UNION
SELECT 'A' type, 'alpha3' rec1, 'bravo3' rec2 )
, cte2 AS (
SELECT 'X' type, 'zulu01' recX UNION
SELECT 'X' type, 'zulu02' rexX )
and this is wanted output
;WITH cteWanted AS (SELECT 'A' type, 'alpha1' rec1, 'bravo1' rec2, NULL recX UNION
SELECT 'A' type, 'alpha2' rec1, 'bravo2' rec2, NULL recX UNION
SELECT 'A' type, 'alpha3' rec1, 'bravo3' rec2, NULL recX UNION
SELECT 'X' type, NULL rec1, NULL rec2, 'zulu01' recX UNION
SELECT 'X' type, NULL rec1, NULL rec2, 'zulu02' recX )
SELECT * FROM cteTarget

Tx all, I realized that I need to go with HABO solution.

Related

add Exists operator in a union sql query

I have two tables that am using union to combine the result-set of them my problem here is Each SELECT statement within UNION must have the same number of columns and data types, I don't have the same number of columns so am creating null columns
select
d.deal_id as order_id,
EXISTS(select * from table1 c where d.user_id = c.user_id) as IsUser, --this returns boolean value
from table 1 c
union
select
cast(o.id as varchar) as order_id,
coalesce('No_user'::text,'0'::text) as IsUser, --i get an error :UNION types boolean and character varying cannot be matched
from table2 o
how can I create a null column in table2 that matches the boolean data type of the table1
how can I create a null column in table2 that matches the boolean data type of the table1
By putting NULL into the SELECT list of the second query.
Generally (in SQL) the datatype for the column is dictated by the first query in the union set and other queries must match. You don't need column aliases for subsequent queries either, but they may help make a query more readable:
select
d.deal_id as order_id,
EXISTS(select * from table1 c where d.user_id = c.user_id) as IsUser, --this returns boolean value
from table 1 c
union
select
cast(o.id as varchar) as order_id,
null --IsUser
from table2 o
If you have a case where the type of the column in the first query is different to what you want in the output, you cast the first column:
select 1::boolean as boolcol
UNION
select true
This will ensure that the column is boolean, rather than giving a "integer and bool cannot be matched". Remember also that, should you need to, NULL can be cast to a type, e.g. select null::boolean as bolcol

Return multiple columns on single CASE DB2

Is it possible to return multiple column on single CASE evaluation in DB2?
below query return single column.
select (case when 1=1 then 0 else 1 end) as col from table;
I need multiple column like
select (case when 1=1 then 0 as col, 1 as col1 else 2 as col1 , 3 as col2 end) from table;
select (case when 1=1 then 0,1 else 2, 3 end)col , col1 from table;
Is coalesce function is use full for above conditions? thanks.
It’s not possible with a single CASE statement in Db2.
But you may use something like below.
select
coalesce(t1.c1, t2.c1, t3.c1) c1
, coalesce(t1.c2, t2.c2, t3.c2) c2
from
(
select tabschema, tabname, rownumber() over (partition by tabschema) rn_
from syscat.tables
) b
left join table(values ('_SYSIBM_', b.tabname)) t1 (c1, c2) on b.tabschema='SYSIBM'
left join table(values ('_SYSCAT_', b.tabname)) t2 (c1, c2) on b.tabschema='SYSCAT'
cross join table(values (b.tabschema, b.tabname)) t3 (c1, c2)
where b.rn_=1;
The sub-select on syscat.tables is constructed to return only one table from each schema just to show the idea (your base table must be there instead of it). "Case condition" here is what you see in the on clause of each join. "Returned values" of this "Case expression" are inside the values clauses.
A CASE statement can be re-written as a UNION. Logically they are the same thing.
So, you could do this
select 0 as col, 1 as col1 from table where 1=1
UNION ALL
select 2 as col, 3 as col1 from table where NOT 1=1 OR 1=1 IS NULL

Sybase Subgroup Order By

I'm trying to join a sub query but as the table contains no unique row_id and I need the most recent record of a specific type, I want to do an Order by Date Desc and get the Top 1 from that, but it doesn't seem allowed in Sybase ASE.
I put together a small sample to show kinda what i'm trying to do.
CREATE TABLE #test_users (USER_ID CHAR(9), USER_CK INT)
INSERT INTO #test_users (USER_ID, USER_CK)
SELECT 'QA0000001', 123000010
UNION ALL SELECT 'QA0000002', 123000020
UNION ALL SELECT 'QA0000003', 123000030
UNION ALL SELECT 'QA0000004', 123000040
UNION ALL SELECT 'QA0000005', 123000050
CREATE TABLE #test_records (STAT_TYPE CHAR(3), USER_CK INT, MOD_DT DATE, PLAN_ID CHAR(1))
INSERT INTO #test_records (STAT_TYPE, USER_CK, MOD_DT, PLAN_ID)
SELECT 'ADD', 123000010, '8/1/2017', 'A'
UNION ALL SELECT 'TRM', 123000010, '6/1/2018', 'A'
UNION ALL SELECT 'ADD', 123000010, '6/1/2018', 'B'
UNION ALL SELECT 'ADD', 123000020, '5/1/2017', 'A'
UNION ALL SELECT 'TRM', 123000020, '9/1/2018', 'A'
UNION ALL SELECT 'ADD', 123000030, '3/1/2018', 'A'
UNION ALL SELECT 'ADD', 123000040, '4/1/2018', 'A'
UNION ALL SELECT 'ADD', 123000050, '1/1/2018', 'B'
UNION ALL SELECT 'TRM', 123000050, '7/1/2018', 'B'
UNION ALL SELECT 'ADD', 123000050, '7/1/2018', 'A'
--Want to know everyone that has ever been in Plan A, and what their last status type was.
--Should return
-- QA0000001, A, TRM, 6/1/2018
-- QA0000002, A, TRM, 9/1/2018
-- QA0000003, A, ADD, 3/1/2018
-- QA0000004, A, ADD, 4/1/2018
-- QA0000005, A, ADD, 7/1/2018
SELECT u.USER_ID, r.PLAN_ID, r.STAT_TYPE, r.MOD_DT FROM #test_users u
LEFT JOIN #test_records r
ON PLAN_ID = 'A'
AND u.USER_CK = r.USER_CK
Thanks for any help you could provide.
Mike

PostgreSQL - How to get distinct on two columns separately?

I've a table like this:
Source table "tab"
column1 column2
x 1
x 2
y 1
y 2
y 3
z 3
How can I build the query to get result with unique values in each of two columns separately. For example I'd like to get a result like one of these sets:
column1 column2
x 1
y 2
z 3
or
column1 column2
x 2
y 1
z 3
or ...
Thanks.
What you're asking for is difficult because it's weird: SQL treats rows as related fields but you're asking to make two separate lists (distinct values from col1 and distinct values from col2) then display them in one output table not caring how the rows match up.
You can so this by writing the SQL along those lines. Write a separate select distinct for each column, then put them together somehow. I'd put them together by giving each row in each results a row number, then joining them both to a big list of numbers.
It's not clear what you want null to mean. Does it mean there's a null in one of the columns, or that there's not the same number of distinct values in each column? This one problem from asking for things that don't match up with typical relational logic.
Here's an example, removing the null value from the data since that confuses the issue, different data values to avoid confusing rowNumber with data and so there are 3 distinct values in one column and 4 in another. This works for SQL Server, presumably there's a variation for PostgreSQL.
if object_id('mytable') is not null drop table mytable;
create table mytable ( col1 nvarchar(10) null, col2 nvarchar(10) null)
insert into mytable
select 'x', 'a'
union all select 'x', 'b'
union all select 'y', 'c'
union all select 'y', 'b'
union all select 'y', 'd'
union all select 'z', 'a'
select c1.col1, c2.col2
from
-- derived table giving distinct values of col1 and a rownumber column
( select col1
, row_number() over (order by col1) as rowNumber
from ( select distinct col1 from mytable ) x ) as c1
full outer join
-- derived table giving distinct values of col2 and a rownumber column
( select col2
, row_number() over (order by col2) as rowNumber
from ( select distinct col2 from mytable ) x ) as c2
on c1.rowNumber = c2.rowNumber

T-SQL Replacing Nulls with Empty String

I have the following union query:
select
'type1' as type,
id,
add_date
from Table A
where type = type1
union all
select
'type2' as type,
id,
'' as add_date
from Table B
Since add_date isn't applicable to type 2, it is providing 1900-01-01 00:00:00.000 for any records returned. I could change the statement from '' as add_date to NULL as add_date, but the user is asking if I can remove the null from the report and leave the result as an empty string where applicable. What is the best way to accomplish this? Thanks.!
You can use null and cast the result as a string with the ISNULL function applied:
SELECT [type], id, ISNULL(CAST(add_date as VARCHAR), '') AS add_date
FROM (
SELECT 'type1' as [type]
,id
,add_date
FROM TableA
UNION
SELECT 'type2' as [type]
,id
,null as add_date
FROM TableB
) inside_query
This will allow you to provide blanks instead of 1/1/1900 or NULL keyword. You can also change the CAST to a CONVERT if you need to provide specific date formatting.
try this:
select
'type1' as type,
id,
CAST(add_date AS VARCHAR) as add_date
from Table A
where type = type1
union all
select
'type2' as type,
id,
'' as add_date
from Table B