SQL CASE with multiple join - sql

I am trying to run a sql select code as below. I am trying to fetch the trans_date which will either be in asutrans or asuhistr. But the below code doesnt give me any value and nor does it fail.
Do you think we can use CASE statement like that?
SELECT
v.voucher_no,
CASE
WHEN t.voucher_no = v.voucher_no THEN t.trans_date
ELSE t1.trans_date
END AS valuedate
FROM
aipdethis v
JOIN asutrans t ON t.client = v.client and t.voucher_no = v.voucher_no
JOIN asuhistr t1 ON t1.client = v.client and t1.voucher_no = v.voucher_no
WHERE
v.voucher_no ='22094200'
If I run the codes separately, then it does give me the result from asihistr. As below-
SELECT
v.voucher_no, t1.trans_Date FROM aipdethis v
JOIN asuhistr t1 ON t1.client = v.client and t1.voucher_no = v.voucher_no
WHERE
v.voucher_no ='22094200'

You cannot have case statement which checks voucher_no because you are already joining in the join query. I think this is what you're expecting:
select
v.voucher_no,
CASE
WHEN t.trans_date is null then t1.trans_date
ELSE t.trans_date
END AS valuedate
FROM aipdethis v
JOIN asutrans t ON t.client = v.client and t.voucher_no = v.voucher_no
JOIN asuhistr t1 ON t1.client = v.client and t1.voucher_no = v.voucher_no
where v.voucher_no ='22094200';

Related

Getting error tb_sales_person_source.id is invalid in the select list in SQL Server

I am new to SQL Server, I have below query which is working fine in Mysql server, but it is not working in SQL Server, I get an error:
tb_sales_person_source.id is invalid in the select list
Can anyone please help me how can I resolve this error ?
SELECT
tb_sales_person_source.id,
tb_sales_person_source.name,
tb_sales_person_source.display_name,
tb_sales_person_source.mapped_sales_person_source_id,
tb_sales_person_source.company_id,
tb_sales_person_source.gm_created,
tb_sales_person_source.gm_modified,
COUNT(tb_Episode.id) AS total_soc,
SOCDate, MonthSOC
FROM
tb_Episode
JOIN
tb_sales_person_source ON tb_sales_person_source.id = tb_Episode.sales_referral_source_id
WHERE
(BranchID = '238' OR BranchID = '239' OR BranchID = '240' OR BranchID = '241')
AND tb_Episode.CustID = '27'
AND PayerType = 'Ep'
AND SOC = 1
AND SOCDate >= '2016-04-01'
AND SOCDate < '2017-5-01'
GROUP BY
sales_referral_source_id, MonthSOC
ORDER BY
tb_sales_person_source.id ASC, tb_Episode.SOCDate ASC;
In SQL server, you must have to add all the columns of "SELECT" in "Group by" apart from the column which is used in the aggregate function
SELECT tb_sales_person_source.id
,tb_sales_person_source.NAME
,tb_sales_person_source.display_name
,tb_sales_person_source.mapped_sales_person_source_id
,tb_sales_person_source.company_id
,tb_sales_person_source.gm_created
,tb_sales_person_source.gm_modified
,count(tb_Episode.id) AS total_soc
,SOCDate
,MonthSOC
FROM tb_Episode
JOIN tb_sales_person_source ON tb_sales_person_source.id = tb_Episode.sales_referral_source_id
WHERE (
BranchID = '238'
OR BranchID = '239'
OR BranchID = '240'
OR BranchID = '241'
)
AND tb_Episode.CustID = '27'
AND PayerType = 'Ep'
AND SOC = 1
AND SOCDate >= '2016-04-01'
AND SOCDate < '2017-5-01'
GROUP BY sales_referral_source_id
,MonthSOC
,tb_sales_person_source.id
,tb_sales_person_source.NAME
,tb_sales_person_source.display_name
,tb_sales_person_source.mapped_sales_person_source_id
,tb_sales_person_source.company_id
,tb_sales_person_source.gm_created
,tb_sales_person_source.gm_modified
,SOCDate
ORDER BY tb_sales_person_source.id ASC
,tb_Episode.SOCDate ASC
It is impossible to accurately re-write your query until you update it to make it clear which table each column comes from.
The important piece of information you need to be aware of, however, is that when using GROUP BY every field in the SELECT must either have an aggregate function around it (MIN(), or MAX(), or SUM(), etc, etc), or be mentioned in the GROUP BY.
This means that the following is NOT valid SQL...
SELECT
t1.some_id,
t1.name,
t1.whatever,
COUNT(t2.id),
SUM(t2.value)
FROM
t1
INNER JOIN
t2
ON t2.some_id = t1.some_id
GROUP BY
t1.some_id
Instead you need one of the following...
SELECT
t1.some_id ,
t1.name,
t1.whatever,
COUNT(t2.id),
SUM(t2.value)
FROM
t1
INNER JOIN
t2
ON t2.some_id = t1.some_id
GROUP BY
t1.some_id,
t1.name,
t1.whatever
Or...
SELECT
t1.some_id,
MAX(t1.name),
MAX(t1.whatever),
COUNT(t2.id),
SUM(t2.value)
FROM
t1
INNER JOIN
t2
ON t2.some_id = t1.some_id
GROUP BY
t1.some_id
The same is true even if you are grouping by a column from table 2.
So, this is invalid too...
SELECT
t1.some_id,
t1.name,
t2.a_date,
COUNT(t2.id),
SUM(t2.value)
FROM
t1
INNER JOIN
t2
ON t2.some_id = t1.some_id
GROUP BY
t2.a_date
This time, however, you have an extra option. Use a sub-query to group up the data in table 2 first...
SELECT
t1.some_id,
t1.name,
t2_agg.a_date,
t2_agg.count_rows,
t2_agg.total_value
FROM
t1
INNER JOIN
(
SELECT
some_id,
a_date,
COUNT(t2.id) AS count_rows,
SUM(t2.value) AS total_value
FROM
t2
GROUP BY
some_id,
a_date
)
t2_agg
ON t2_agg.some_id = t1.some_id
If you fully qualify your query (so I can see which table every column comes from) then I can show you how to use this method to suit your exact case.
Finally i resolved my query, here is my query, thanks to all of you for your help
SELECT tb_sales_person_source.id, tb_sales_person_source.name, tb_sales_person_source.display_name, count(tb_Episode.id) as total_soc, MonthSOC
FROM tb_Episode
JOIN tb_sales_person_source ON tb_sales_person_source.id = tb_Episode.sales_referral_source_id
WHERE ( BranchID = '238' or BranchID = '239' or BranchID = '240' or BranchID = '241')
AND tb_Episode.CustID = '27'
AND PayerType = 'Ep'
AND SOC = 1
AND SOCDate >= '2016-04-01'
AND SOCDate < '2017-5-01'
GROUP BY tb_sales_person_source.id, tb_sales_person_source.name, tb_sales_person_source.display_name, sales_referral_source_id, MonthSOC
ORDER BY tb_sales_person_source.id asc

How to make a cell blank in a row from a query result?

I have a query as below:
SELECT
cc.chain_desc as chain_desc
,cc.chain_id as chain_id
,COUNT(distinct t.trans_id) as TranCount
FROM TRANSACTION AS t
LEFT OUTER JOIN location AS l
ON t.location_id = l.location_id
LEFT OUTER JOIN trans_line AS tl
ON t.trans_id = tl.trans_id
LEFT OUTER JOIN contract as c
ON t.contract_id = c.contract_id
LEFT OUTER JOIN chain_desc as cc
ON l.chain_id = cc.chain_id
WHERE
t.loc_country = 'U'
AND c.issuer_id IN (156966,166203)
AND t.trans_date >= '2016-10-01 00:00'
and t.trans_date < '2016-10-31 00:00'
AND tl.cat NOT IN ('DEF','DEFD','DEFC')
GROUP BY cc.chain_desc, cc.chain_id
UNION
SELECT
'TOTAL'
,0
,COUNT(distinct t.trans_id)
FROM TRANSACTION AS t
LEFT OUTER JOIN location AS l
ON t.location_id = l.location_id
LEFT OUTER JOIN trans_line AS tl
ON t.trans_id = tl.trans_id
LEFT OUTER JOIN contract as c
ON t.contract_id = c.contract_id
LEFT OUTER JOIN chain_desc as cc
ON l.chain_id = cc.chain_id
WHERE
t.loc_country = 'U'
AND c.issuer_id IN (156966,166203)
AND t.trans_date >= '2016-10-01 00:00'
and t.trans_date < '2016-10-31 00:00'
AND tl.cat NOT IN ('DEF','DEFD','DEFC')
The above query when executed reurns the below result:
I need the result to be displayed as below:
The column "Chain_Id" is of "integer" type, how can I make that blank?.
you can simply select null
.....
UNION
SELECT
'TOTAL'
, NULL::INTEGER
,COUNT(distinct t.trans_id)
FROM TRANSACTION AS t
LEFT OUTER JOIN location AS l
ON t.location_id = l.location_id
LEFT OUTER JOIN trans_line AS tl
ON t.trans_id = tl.trans_id
LEFT OUTER JOIN contract as c
ON t.contract_id = c.contract_id
LEFT OUTER JOIN chain_desc as cc
ON l.chain_id = cc.chain_id
WHERE
t.loc_country = 'U'
AND c.issuer_id IN (156966,166203)
AND t.trans_date >= '2016-10-01 00:00'
and t.trans_date < '2016-10-31 00:00'
AND tl.cat NOT IN ('DEF','DEFD','DEFC')
because null is not a type you could try add above the first query
DEFINE test INT;
LET test = NULL;
......
SELECT
'TOTAL'
, test
,COUNT(distinct t.trans_id)
.....
Or like suggusted by #Jonathan Leffler use NULL::INTEGER or CAST(NULL AS INTEGER)
In Informix you can use NULL in the projection list, but the column must have a type. Since in Informix NULL does not have a type, you need to use a CAST.
SELECT NULL::INTEGER AS id FROM systables WHERE tabid = 1;
SELECT CAST(NULL AS INTEGER) AS id FROM systables WHERE tabid = 1;
You can check the answers to this other question (Informix: Select null problem).
You can check the IBM Knowledge Center (NULL Keyword).
One way is to convert to NULL:
(case when cc.chain_id <> 0 then cc.chain_id end) as chain_id
Another is to convert everything to a string:
(case when cc.chain_id <> 0 then cast(cc.chain_id as varchar(255)) else '' end) as chain_id

Write query using JOINS

select
store, sum(value)
from
rms.sa_tran_head
where
store_day_seq_no in (select store_day_seq_no
from rms.sa_store_day
where store in (3003)
and business_date = '01-JAN-2015')
and tran_type in ('SALE', 'RETURN')
group by
store;
How to write the above query using JOINS..
SELECT
sd.store,
SUM(TH.VALUE) AS GROSS ,
SUM(ti.qty) AS QTY
FROM rms.sa_tran_head AS th
JOIN rms.sa_store_day AS sd
ON th.store_day_seq_no = sd.store_day_seq_no
JOIN rms.sa_tran_item AS ti
ON ti.tran_seq_no = th.tran_seq_no
WHERE sd.store in (3003) --in (3003) use in if more than 1 value
AND sd.business_date = '01-JAN-2015'
AND th.tran_type IN ('SALE','RETURN')
GROUP BY
sd.store;
When I add other columns of another table it is showing different values...
I assumed store_day_seq_no is FK for the table rms.sa_store_day and the query with JOIN like this,
SELECT
sd.store,
SUM(sd.value) AS [Sum]
FROM rms.sa_tran_head AS th
JOIN rms.sa_store_day AS sd
ON th.store_day_seq_no = sd.store_day_seq_no
WHERE
sd.store = 3003 --in (3003) use in if more than 1 value
AND sd.business_date = '01-JAN-2015'
AND th.tran_type IN ('SALE','RETURN')
GROUP BY
sd.store;
I think this is ok.
SELECT
t1.store,
SUM(t1.Value) AS Sum_Value
FROM rms.sa_tran_head t1
INNER JOIN sa_store_day t2 ON t1.store_day_seq_no = t2.store_day_seq_no
WHERE t2.store IN ( 3003 )
AND t2.business_date = '01-JAN-2015'
AND t1.tran_type IN ( 'SALE' , 'RETURN' )
GROUP BY t1.store

Invoke a column twice with different conditions

I really appreciate any help with this matter :)
Am Working on a Report now and I had faced some troubles
I have this Query and it work fine , now I want to add a coulmn that is already exist in the query(from the same table) , but this time i'll change the condition of it , BTW the conditions in both of the 2 column are based on one other column
like for example If I have this :
Select Price from ITM1 WHERE PriceList = '1'
and also this
Select Price from ITM1 WHERE PriceList = '10'
how I can write in the same query and let them display in two different column ?
I will put the Query here in case if some one can help me through it :
you can see THE Column Price & PriceList in the lower part of it ,Bolded.
I just need to make the samething again but with a new coulmn name thats it.
Using the IN Operator will give you what you want. However, there are other changes that you can make to your query which would boost performance - but it's out of scope to the question. I'm unclear as to what you're trying to do with the different "columns" Please help explain. Else see #Dave.Gugg's answer which does just that.
SELECT T0.ItemCode,
T0.ItemName,
T0.CardCode,
T0.CodeBars,
T2.UgpCode,
T3.AltQty,
T3.BaseQty,
CASE
WHEN T4.Uomentry = - 1
THEN T0.[BuyUnitMsr]
ELSE t4.UomName
END AS 'UoMName',
T4.UomEntry,
T0.U_CAT_CODE,
T0.U_CAT_NAME,
T1.CardName,
(
SELECT TOP (1) dbo.PDN1.U_AC_QTY_ORDER
FROM dbo.PDN1
INNER JOIN dbo.OPDN ON dbo.PDN1.DocEntry = dbo.OPDN.DocEntry
WHERE (dbo.PDN1.ItemCode = T0.ItemCode)
AND (dbo.OPDN.CardCode = T0.CardCode)
ORDER BY dbo.OPDN.DocDate DESC
) AS OQuantity,
(
SELECT TOP (1) PDN1_1.U_AC_QTY_BONUS
FROM dbo.PDN1 AS PDN1_1
INNER JOIN dbo.OPDN AS OPDN_1 ON PDN1_1.DocEntry = OPDN_1.DocEntry
WHERE (PDN1_1.ItemCode = T0.ItemCode)
AND (OPDN_1.CardCode = T0.CardCode)
ORDER BY OPDN_1.DocDate DESC
) AS BQuantity,
ITM1.Price,
T0.U_DISC_PER
FROM dbo.OITM AS T0
INNER JOIN dbo.OCRD AS T1 ON T0.CardCode = T1.CardCode
INNER JOIN dbo.OUGP AS T2 ON T0.UgpEntry = T2.UgpEntry
INNER JOIN dbo.UGP1 AS T3 ON T2.UgpEntry = T3.UgpEntry
INNER JOIN dbo.ITM1 ON T0.ItemCode = dbo.ITM1.ItemCode
AND dbo.ITM1.PriceList IN ('1', '10')
LEFT JOIN dbo.OUOM AS T4 ON T3.UomEntry = T4.UomEntry
WHERE (T0.Series = '65')
AND (
T4.UomEntry = 3
OR T4.UomEntry = '-1'
)
If you want a different column (this may perform better than two joins):
SELECT T0.ItemCode,
T0.ItemName,
T0.CardCode,
T0.CodeBars,
T2.UgpCode,
T3.AltQty,
T3.BaseQty,
CASE
WHEN T4.Uomentry = - 1
THEN T0.[BuyUnitMsr]
ELSE t4.UomName
END AS 'UoMName',
T4.UomEntry,
T0.U_CAT_CODE,
T0.U_CAT_NAME,
T1.CardName,
(
SELECT TOP (1) dbo.PDN1.U_AC_QTY_ORDER
FROM dbo.PDN1
INNER JOIN dbo.OPDN ON dbo.PDN1.DocEntry = dbo.OPDN.DocEntry
WHERE (dbo.PDN1.ItemCode = T0.ItemCode)
AND (dbo.OPDN.CardCode = T0.CardCode)
ORDER BY dbo.OPDN.DocDate DESC
) AS OQuantity,
(
SELECT TOP (1) PDN1_1.U_AC_QTY_BONUS
FROM dbo.PDN1 AS PDN1_1
INNER JOIN dbo.OPDN AS OPDN_1 ON PDN1_1.DocEntry = OPDN_1.DocEntry
WHERE (PDN1_1.ItemCode = T0.ItemCode)
AND (OPDN_1.CardCode = T0.CardCode)
ORDER BY OPDN_1.DocDate DESC
) AS BQuantity,
CASE
WHEN ITM1.PriceList = '1'
THEN ITM1.Price
ELSE '0'
END AS Price1,
CASE
WHEN ITM1.PriceList = '10'
THEN ITM1.Price
ELSE '0'
END AS Price2,
T0.U_DISC_PER
FROM dbo.OITM AS T0
INNER JOIN dbo.OCRD AS T1 ON T0.CardCode = T1.CardCode
INNER JOIN dbo.OUGP AS T2 ON T0.UgpEntry = T2.UgpEntry
INNER JOIN dbo.UGP1 AS T3 ON T2.UgpEntry = T3.UgpEntry
INNER JOIN dbo.ITM1 ON T0.ItemCode = dbo.ITM1.ItemCode
AND dbo.ITM1.PriceList IN ('1', '10')
LEFT JOIN dbo.OUOM AS T4 ON T3.UomEntry = T4.UomEntry
WHERE (T0.Series = '65')
AND (
T4.UomEntry = 3
OR T4.UomEntry = '-1'
)
You should be able to just join to the table a second time, but you will need to make the joins outer:
SELECT T0.ItemCode ,
T0.ItemName ,
T0.CardCode ,
T0.CodeBars ,
T2.UgpCode ,
T3.AltQty ,
T3.BaseQty ,
CASE WHEN T4.Uomentry = -1 THEN T0.[BuyUnitMsr]
ELSE t4.UomName
END AS 'UoMName' ,
T4.UomEntry ,
T0.U_CAT_CODE ,
T0.U_CAT_NAME ,
T1.CardName ,
( SELECT TOP ( 1 )
dbo.PDN1.U_AC_QTY_ORDER
FROM dbo.PDN1
INNER JOIN dbo.OPDN ON dbo.PDN1.DocEntry = dbo.OPDN.DocEntry
WHERE ( dbo.PDN1.ItemCode = T0.ItemCode )
AND ( dbo.OPDN.CardCode = T0.CardCode )
ORDER BY dbo.OPDN.DocDate DESC
) AS OQuantity ,
( SELECT TOP ( 1 )
PDN1_1.U_AC_QTY_BONUS
FROM dbo.PDN1 AS PDN1_1
INNER JOIN dbo.OPDN AS OPDN_1 ON PDN1_1.DocEntry = OPDN_1.DocEntry
WHERE ( PDN1_1.ItemCode = T0.ItemCode )
AND ( OPDN_1.CardCode = T0.CardCode )
ORDER BY OPDN_1.DocDate DESC
) AS BQuantity ,
dbo.ITM1.Price ,
ITM1Second.Price,
T0.U_DISC_PER
FROM dbo.OITM AS T0
INNER JOIN dbo.OCRD AS T1 ON T0.CardCode = T1.CardCode
INNER JOIN dbo.OUGP AS T2 ON T0.UgpEntry = T2.UgpEntry
INNER JOIN dbo.UGP1 AS T3 ON T2.UgpEntry = T3.UgpEntry
LEFT OUTER JOIN dbo.ITM1 ON T0.ItemCode = dbo.ITM1.ItemCode
AND dbo.ITM1.PriceList = '10'
LEFT OUTER JOIN dbo.ITM1 ITM1Second ON T0.ItemCode = ITM1Second.ItemCode
AND ITM1Second.PriceList = '1'
LEFT OUTER JOIN dbo.OUOM AS T4 ON T3.UomEntry = T4.UomEntry
WHERE ( T0.Series = '65' )
AND ( T4.UomEntry = 3
OR T4.UomEntry = '-1'
)

inner join results of "with" clause

I have 2 with clauses like this:
WITH T
AS (SELECT tfsp.SubmissionID,
tfsp.Amount,
tfsp.campaignID,
cc.Name
FROM tbl_FormSubmissions_PaymentsMade tfspm
INNER JOIN tbl_FormSubmissions_Payment tfsp
ON tfspm.SubmissionID = tfsp.SubmissionID
INNER JOIN tbl_CurrentCampaigns cc
ON tfsp.CampaignID = cc.ID
WHERE tfspm.isApproved = 'True'
AND tfspm.PaymentOn >= '2013-05-01 12:00:00.000' AND tfspm.PaymentOn <= '2013-05-07 12:00:00.000')
SELECT SUM(Amount) AS TotalAmount,
campaignID,
Name
FROM T
GROUP BY campaignID,
Name;
and also:
WITH T1
AS (SELECT tfsp.SubmissionID,
tfsp.Amount,
tfsp.campaignID,
cc.Name
FROM tbl_FormSubmissions_PaymentsMade tfspm
INNER JOIN tbl_FormSubmissions_Payment tfsp
ON tfspm.SubmissionID = tfsp.SubmissionID
INNER JOIN tbl_CurrentCampaigns cc
ON tfsp.CampaignID = cc.ID
WHERE tfspm.isApproved = 'True'
AND tfspm.PaymentOn >= '2013-05-08 12:00:00.000' AND tfspm.PaymentOn <= '2013-05-14 12:00:00.000')
SELECT SUM(Amount) AS TotalAmount,
campaignID,
Name
FROM T1
GROUP BY campaignID,
Name;
Now I want to join the results of the both of the outputs. How can I do it?
Edited: Added the <= cluase also.
Reults from my first T:
Amount-----ID----Name
1000----- 2-----Annual Fund
83--------1-----Athletics Fund
300-------3-------Library Fund
Results from my T2
850-----2-------Annual Fund
370-----4-------Other
The output i require:
1800-----2------Annual Fund
83-------1------Athletics Fund
300------3-------Library Fund
370------4-----Other
You don't need a join. You can use
SELECT SUM(tfspm.PaymentOn) AS Amount,
tfsp.campaignID,
cc.Name
FROM tbl_FormSubmissions_PaymentsMade tfspm
INNER JOIN tbl_FormSubmissions_Payment tfsp
ON tfspm.SubmissionID = tfsp.SubmissionID
INNER JOIN tbl_CurrentCampaigns cc
ON tfsp.CampaignID = cc.ID
WHERE tfspm.isApproved = 'True'
AND ( tfspm.PaymentOn BETWEEN '2013-05-01 12:00:00.000'
AND '2013-05-07 12:00:00.000'
OR tfspm.PaymentOn BETWEEN '2013-05-08 12:00:00.000'
AND '2013-05-14 12:00:00.000' )
GROUP BY tfsp.campaignID,
cc.Name
If I am right, after a WITH-clause you have to immediatly select the results of that afterwards. So IMHO your best try to achieve joining the both would be to save each of them into a temporary table and then join the contents of those two together.
UPDATE: after re-reading your question I realized that you probably don't want a (SQL-) join but just your 2 results packed together in one, so you could easily achieve that with what I descibed above, just select the contents of both temporary tables and put a UNION inbetween them.
I was thinking it wrongly. Thanks for the help. This is how i achieved what exactly i want:
WITH
T AS (
SELECT tfsp.SubmissionID , Amount1 =
CASE
WHEN tfspm.PaymentOn >= '2013-01-10 11:34:54.000' AND tfspm.PaymentOn <= '2013-04-10 11:34:54.000' THEN tfsp.Amount
END
, Amount2 =
CASE
WHEN tfspm.PaymentOn >= '2013-05-01 11:34:54.000' AND tfspm.PaymentOn <= '2013-05-23 11:34:54.000' THEN tfsp.Amount
END
, tfsp.campaignID , cc.Name FROM tbl_FormSubmissions_PaymentsMade tfspm
INNER JOIN tbl_FormSubmissions_Payment tfsp ON tfspm.SubmissionID = tfsp.SubmissionID
INNER JOIN tbl_CurrentCampaigns cc ON tfsp.CampaignID = cc.ID
WHERE tfspm.isApproved = 'True'
)
SELECT ISNULL(SUM(Amount1),0) AS TotalAmount1, ISNULL(SUM(Amount2),0) AS TotalAmount2, campaignID , Name FROM T GROUP BY campaignID, Name;