how to combine two result sets without nulls - sql

I have two result sets that I would like to combine , since I would like to send them as a dataset to my ssrs report.
I am currently doing :
Select Sum(Teamsales) as TS, Null as PS from ABC;
union
Select null as TS, Sum(ProdSales) From DEF;
I get an output like this :
123 NULL
NULL 456
Is there a way I can get an output as below ??
123 456

SELECT Sum(Teamsales) as TS,
(
SELECT Sum(ProdSales)
FROM DEF
) AS PS
FROM ABC

Maybe something like this?
select
sum(teamsales) as ts,
Sum(ProdSales) as ps
from
abc cross join
def
(Crossjoins are generally evil... But you could consider maybe to use more strict one.)

Most probably you would be having more than one row in each result set.
As you would apply a dimension in group by clause.
for example
You want to get total Team Sales and total Product sales for each branch then you should write.
Select ABC.BranchID, ABC.TS, DEF.PS
(Select BranchID, Sum(Teamsales) as TS from ABC group by BranchID) ABC
Inner Join
(Select BranchID, Sum(ProdSales) as PS From DEF group by BranchID) DEF
On ABC.BranchID = DEF.BranchID

Since these are both one-liners, you could just cross-join the results, giving you a single line:
SELECT SUM(Teamsales) as TS,
FROM abc
CROSS JOIN (SELECT SUMN(ProdSales) FROM def) t

Try this:
select sum(TS), sum(PS) from (
Select Sum(Teamsales) as TS, Null as PS from ABC
union all
Select null as TS, Sum(ProdSales) as PS From DEF
) as x

Related

Mapping All Terminal IDs to Previous IDs

I have a table in SQL Server that contains a list of all ID migrations overtime. An individual's ID can change overtime, and this table helps us understand when the change occurs, and what the ID changes from/to. What I'd ultimately like is a way to list all of the previous IDs for the most recent ID (which I'm referring to as the terminal ID). I'm assuming this will require some sort of CTE, but my brain is in a bit of a fog as to how I should set this up.
CREATE TABLE #ExampleIdCrosswalk
(
CurrentId VARCHAR(3)
,PreviousId VARCHAR(3)
,PreviousIdObsoleteDate DATE
)
INSERT INTO #ExampleIdCrosswalk
VALUES
('DEF','ABC','2021-01-01')
,('WVU','ZYX','2021-01-01')
,('MNO','ONM','2021-02-01')
,('PPP','EEE','2021-02-01')
,('GHI','DEF','2021-03-01')
,('TSR','WVU','2021-03-01')
,('NRP','QRS','2021-03-01')
,('JKL','GHI','2021-04-01')
SELECT * FROM #ExampleIdCrosswalk
Ultimately, what I'd like to show is a table with all the terminal ID's along with each of their corresponding previous IDs.
Any help would be appreciated!
You can use a recursive CTE for this:
with cte as (
select currentid, previousid
from ExampleIdCrosswalk ec
where not exists (select 1 from ExampleIdCrosswalk ec2 where ec2.previousId = ec.currentid)
union all
select cte.currentid, ec.previousid
from cte join
ExampleIdCrosswalk ec
on ec.currentId = cte.previousId
)
select *
from cte;
Here is a db<>fiddle.
You can use a recursive CTE, as in:
with
n (last, curr, prev) as (
select currentid, currentid, previousid
from ExampleIdCrosswalk where currentid not in (
select previousid from ExampleIdCrosswalk
)
union all
select n.last, c.currentid, c.previousid
from n
join ExampleIdCrosswalk c on c.currentid = n.prev
)
select last, prev
from n
order by last, prev
Result:
last prev
----- ----
JKL ABC
JKL DEF
JKL GHI
MNO ONM
NRP QRS
PPP EEE
TSR WVU
TSR ZYX
See running example at db<>fiddle.

logic to create more rows in sql

I have a table1 that I wanted to transform into the expected table.
Expected table logic for columns:
cal: comes from cal of table1. ID comes from the ID of table1.
code: this is populated with lp or fp depending upon if we have a value in f_a then we create a new record with fp as code. corresponding to it we check if f_a is populated if yes then we take that date from f_a and put in in the Al column for the same ID. also we check if f_pl is populated if yes then we take the date from that and put it in the pl column.
If the code was lp then we check if l_a is populated then we take that date and place in the date in Al for that code and Id. also, we check if lpl is populated if yes then we take that date and put it in pl.
I am just a starter with SQL so it is a bit overwhelming for me on how to get it started. Please post some solutions.
table1:
ID f_a l_a f_pl lpl cal
CNT 6/20/2018 6/28/2018 6/28/2018 1/31/2020
expected output:
ID Cal code pl Al
CNT 1/31/2020 lp 6/28/2018 6/28/2018
CNT 1/31/2020 fp 6/20/2018
Update:
I have more IDs in the table, so it is not that CNT is the only Id. If I use unpivot then it should follow the same logic for all IDs.
This is a question about how to unpivot columns to rows. In Oracle, I would recommend a lateral join:
select t.id, t.cal, x.*
from mytable t
cross apply (
select 'lp' as code, t.lpl as pl, l_a as al from dual
union all
select 'fp', t.f_pl, t.f_a from dual
) x
This syntax is available in Oracle 12.1 onwards. In earlier versions, you would use union all:
select id, cal, 'lp' as code, lpl as pl, l_a as al from mytable
union all
select id, cal, 'lp' as code, 'fp', f_pl, f_a from mytable
You can use UNPIVOT for multiple columns then do the checks you need on dates:
with a as (
select
'CNT' as ID,
date '2018-06-20' as f_a,
date '2018-06-28' as l_a,
cast(null as date) as f_pl,
date '2018-06-28' as l_pl,
date '2020-01-31' as cal
from dual
)
select *
from a
unpivot(
(pl, al) for code in ((l_pl, l_a) as 'lp', (f_pl, f_a) as 'fp')
) up
ID | CAL | CODE | PL | AL
CNT | 31-JAN-07 | lp | 28-JUN-18 | 28-JUN-18
CNT | 31-JAN-07 | fp | | 20-JUN-18
Working example here.
Please try this script which is not version dependend:
-- Here we select columns foom source table. Please change the names if they are different
with r as (
select
ID,
f_a,
l_a,
f_pl,
lpl, -- Here not sure if example is wrong or no underscore in column deffinition
cal
from table_1 -- Please put real table name here
)
select * from (
select r.id, r.cal, 'lp' as code, r.l_pl as pl, l_a as ai
from r
where r.l_a is not null
union all
select r1.id, r1.cal, 'pl', r1.f_pl, r1.f_a
from r r1
where r1.f_a is not null
)
order by id, cal, code;

How to get a correlated subquery as column

I dont know how I can do this sql query, probably its simple but I don't know how i can do it.
I have 2 tables:
Table_Articles:
COD NAME
1 Bottle
2 Car
3 Phone
Table_Articles_Registered
COD_ARTICLE DATE
1 05/11/2014
1 06/11/2014
1 07/11/2014
2 08/11/2014
2 09/11/2014
3 05/11/2014
I want take in the table Table_Articles_Registered the row with the MAX date , finally I want get this result:
COD NAME DATE
1 Bottle 07/11/2014
2 Car 09/11/2014
3 Phone 05/11/2014
I need use the sencente like this. The problem its in the subquery. Later I use other inner join in the sentence, this is only a fragment.
select
_Article.Code,
_Article.Description ,
from Tbl_Articles as _Article left join
(
select top 1 *
from ArticlesRegisterds where DATE_REGISTERED <= '18/11/2014'
order by DATE_REGISTERED
)
as regAux
on regAux.CODE_ARTICLE= _Article.CODE
I dont know how can I connect the field CODE_ARTICLE in the table ArticlesRegisterds with the first query.
I think this is a basic aggregation query with a join:
select a.cod, a.name, max(ar.date) as date
from Artiles a join
ArticlesRegisterds ar
on ar.cod_article = a.cod
group by a.cod, a.name
Try this:-
SELECT TAR.COD_ARTICLE, TA.NAME, MAX(TAR.DATE)
FROM Table_Articles_Registered TAR JOIN
Table_Articles.TA ON TAR.COD_ARTICLE = TA.COD
GROUP BY TAR.COD_ARTICLE, TA.NAME;
Can't you just do this?:
SELECT
Table_Articles.COD,
Table_Articles.NAME,
(
SELECT MAX(Table_Articles_Registered.DATE)
FROM Table_Articles_Registered
WHERE Table_Articles.COD_ARTICLE=Table_Articles.COD
) AS DATE
FROM
Table_Articles

SQL - nested select queries

I want to select all dealercode (distinct) and introducercode with iapn. Bbut iapn must be a highest value only.
e.g.
dealercode = 7 and iapin = 3 and introducercode = 3
like that (THIS MUST BE A ONLY VALUE FOR DEALERCODE)
This is my query:
SELECT DISTINCT
dealercode, iapin as iapin,
(SELECT introducercode) as introducecode
FROM
dealerplacement d
where
exists (SELECT MIN(iapin) FROM dealerplacement )
ORDER BY
dealercode, iapin ASC
I have attached with this post data set to this code.
This is the structure. I want to get result as below.
DEALERCODE 1200 iapn 003 and introducercode 203. only.
current database as below.
1200 001 201
1200 002 202
1200 003 203
Please help me to solve this.
Why not just use MAX and GROUP BY or is there something else I am missing
SELECT dealercode,
introducercode,
MAX(iapin) iapin
FROM dealerplacement d
GROUP BY dealercode,
introducercode
Aggregate Functions (Transact-SQL)
EDIT
Re the changes to your request, you might want to try something like
SELECT d.*
FROM dealerplacement d INNER JOIN
(
SELECT dealercode,
MAX(iapin) iapin
FROM dealerplacement d
GROUP BY dealercode
) dM ON d.dealercode = dM.dealercode
AND d.iapin = dM.iapin
It seems like you want the MINIMUM iapin based on your example result. To get the proper corresponding introducecode, you'll need to use a subselect:
SELECT a.dealercode, a.iapin, a.introducecode
FROM dealerplacement a
INNER JOIN
(
SELECT dealercode, MIN(iapin) AS miniapin
FROM dealerplacement
GROUP BY dealercode
) b ON a.dealercode = b.dealercode AND a.iapin = b.miniapin

Logically create templates based on intersection table

I'm not sure how to describe the question, but I'm trying to give suggestions on what codes to attribute to tariffs. I'm doing this in Oracle.
Here's my database structure:
CODE (
CODEID *PK NCHAR(10)
)
CODETARIFF (
TARIFFNO NCHAR(15) *PK *FK
CODEID NCHAR(10) *PK *FK
)
TARIFF (
TARIFFNO NCHAR(15) *PK
)
So I'm trying to logically make templates for what codes should be assigned to tariffs. I'm imagining showing something along the lines of: "6 tariffs also have these 2 codes associated with them"
I tried this, but the counts that are returned for each of the codes aren't really showing a template, they only really show incidences of when that one code appears with the two I've specified.
SELECT COUNT(*), CodeID
FROM CodeTariff
INNER JOIN (
SELECT TariffNo, COUNT(*)
FROM CodeTariff
WHERE CodeID IN ('ABC', 'DEF')
GROUP BY TariffNo
HAVING COUNT(*) > 1) SQ
ON CodeTariff.TariffNo = SQ.TariffNo
WHERE CodeID NOT IN ('ABC', 'DEF')
GROUP BY CodeTariff.CodeID
ORDER BY COUNT(*) DESC;
Sorry if this is confusing.
I don't know if this is even possible, but I'm looking for output like this:
Data:
TariffCode
TariffNo CodeID
1111 ABC
1111 DEF
2222 ABC
2222 DEF
2222 GHI
2222 JKL
3333 ABC
3333 DEF
3333 GHI
3333 JKL
Output: (when given tariff 1111)
CodesToAdd Count
GHI, JKL 2
So that I can display:
2 other tariffs have the codes GHI and JKL associated with them. Would you like to add these codes to tariff 1111?
Try these magics out:
SELECT Code, COUNT(*) AS Count
FROM (SELECT dbo.TariffCode.Tariff, dbo.TariffCode.Code
FROM dbo.TariffCode LEFT OUTER JOIN
(SELECT TariffCode_2.Tariff, TariffCode_2.Code
FROM dbo.TariffCode AS TariffCode_2 INNER JOIN
(SELECT Tariff, Code
FROM dbo.TariffCode AS TariffCode_1
WHERE (Tariff = '1111')) AS TariffsWithSharedCodes ON TariffCode_2.Code = TariffsWithSharedCodes.Code AND
TariffCode_2.Tariff <> '1111') AS MutualCodes ON dbo.TariffCode.Tariff = MutualCodes.Tariff AND
dbo.TariffCode.Code = MutualCodes.Code
WHERE (MutualCodes.Code IS NULL) AND (dbo.TariffCode.Tariff <> '1111')) AS MissingCodes
GROUP BY Code
ORDER BY Count DESC, Code
This is T-SQL, sorry, but you'll get the idea
Hope the script below can help you out. It will get all possible tariffs, not only for '1111':
with temp as (
select tariffno, tariffno2, codeid
from (
select distinct c1.tariffno, c2.tariffno as tariffno2, c2.codeid
from tariffcode c1
join tariffcode c2 on c1.tariffno != c2.tariffno and c1.codeid != c2.codeid
) c1
where
not exists (select 1 from tariffcode where tariffno = c1.tariffno and codeid = c1.codeid)
)
select tariffno, codeid, count(*) as cnt from temp group by tariffno, codeid;