Write query using JOINS - sql

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

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

Easy Left Join SQL Syntax

New to SQL and want to complete a LEFT JOIN.
I have two seperate tables with the below code:
SELECT
StockCode, SalesOrder, SUM(OrderQty)
FROM
dbo.IopSalesPerf
WHERE
dbo.IopSalesPerf.CustRequestDate BETWEEN '2017-07-01' AND '2017-07-31'
AND EntrySystemTime = 1
AND Warehouse = '01'
AND StockCode = '001013'
GROUP BY
StockCode,SalesOrder
ORDER BY
StockCode ASC
SELECT
SalesOrder, SUM(NetSalesValue), SUM(QtyInvoiced)
FROM
ArTrnDetail
GROUP BY
SalesOrder
I would like to LEFT JOIN the last table onto the first using SalesOrder as the joining column. Can anyone assist with the syntax?
Simpliest way would be:
SELECT * FROM
(
SELECT StockCode,SalesOrder,sum(OrderQty)
FROM dbo.IopSalesPerf
WHERE dbo.IopSalesPerf.CustRequestDate between '2017-07-01' and '2017-07-31'
and EntrySystemTime = 1 and Warehouse = '01' and StockCode = '001013'
GROUP BY StockCode,SalesOrder
Order BY StockCode ASc
) AS A
LEFT JOIN
(
SELECT SalesOrder,sum(NetSalesValue),sum(QtyInvoiced)
FROM ArTrnDetail
Group by SalesOrder
) AS B
ON A.SalesOrder = B.SalesOrder

How can I get value from above row with same ID if row is null?

I'm new with SQL and I encountered this.
Here's a screenshot
My question is how can I make all the NULL on primary_payer_id get the value above only if they have same ClientID and ActionCode IS NOT NULL. FYI CustomColumn is only a copy of primary_payer_id ALSO I attached my code here below.
Here's my code:
SELECT ci.client_id AS ClientID,
ci.primary_payer_id,
ci.effective_date AS EffectiveDate,
ci.action_code_id AS ActionCode,
cc.item_description AS ItemDesc,
ap.description AS IDescription,
ci.deleted
FROM census_item ci
LEFT JOIN common_code cc ON ci.adt_tofrom_id = cc.item_id
LEFT JOIN ar_lib_payers ap ON ci.primary_payer_id = ap.payer_id
WHERE ci.deleted = 'N'
There might be a more efficient method, but this will work:
with t as (
<your query here>
)
select t.*,
(case when t.actioncode is not null and t.clientid is null
then tprev.clientid
else t.clientid
end) as new_clientid
from t outer apply
(select top 1 tprev.*
from t tprev
where tprev.clientid = t.clientid and
tprev.effectivedate < t.effectivedate
order by tprev.effecctivedate desc
) tprev;

not able to select a column outside left join

I am working with the below query
SELECT * FROM
(SELECT DISTINCT
a.Number
,a.Description
,ISNULL(temp.Quantity,0) Quantity
,LastReceived
,LastIssued
FROM Article a
LEFT JOIN (
select ss.ArticleId
, ss.Quantity
, max(lastreceiveddate) as LastReceived
, max(lastissueddate) as LastIssued
from StockSummary ss
where ss.UnitId = 8
group by ss.ArticleId, ss.StockQuantity
having (MAX(ss.LastReceivedDate) < '2014-09-01' or MAX(ss.LastReceivedDate) is NULL)
AND (MAX(ss.LastIssuedDate) < '2014-09-01' or MAX(ss.LastIssuedDate) is NULL)
) temp on a.Id = temp.ArticleId
WHERE a.UnitId = 8
) main
ORDER BY main.Number
What i want to achieve is to select the articles only with the MAX(ss.LastReceivedDate) and MAX(ss.LastIssuedDate) condition in the Left join query and then do the Quantity Select in the main query.
Note: the quantity column can be 0 or NULL.
Kindly help

Inner join that ignore singlets

I have to do an self join on a table. I am trying to return a list of several columns to see how many of each type of drug test was performed on same day (MM/DD/YYYY) in which there were at least two tests done and at least one of which resulted in a result code of 'UN'.
I am joining other tables to get the information as below. The problem is I do not quite understand how to exclude someone who has a single result row in which they did have a 'UN' result on a day but did not have any other tests that day.
Query Results (Columns)
County, DrugTestID, ID, Name, CollectionDate, DrugTestType, Results, Count(DrugTestType)
I have several rows for ID 12345 which are correct. But ID 12346 is a single row of which is showing they had a row result of count (1). They had a result of 'UN' on this day but they did not have any other tests that day. I want to exclude this.
I tried the following query
select
c.desc as 'County',
dt.pid as 'PID',
dt.id as 'DrugTestID',
p.id as 'ID',
bio.FullName as 'Participant',
CONVERT(varchar, dt.CollectionDate, 101) as 'CollectionDate',
dtt.desc as 'Drug Test Type',
dt.result as Result,
COUNT(dt.dru_drug_test_type) as 'Count Of Test Type'
from
dbo.Test as dt with (nolock)
join dbo.History as h on dt.pid = h.id
join dbo.Participant as p on h.pid = p.id
join BioData as bio on bio.id = p.id
join County as c with (nolock) on p.CountyCode = c.code
join DrugTestType as dtt with (nolock) on dt.DrugTestType = dtt.code
inner join
(
select distinct
dt2.pid,
CONVERT(varchar, dt2.CollectionDate, 101) as 'CollectionDate'
from
dbo.DrugTest as dt2 with (nolock)
join dbo.History as h2 on dt2.pid = h2.id
join dbo.Participant as p2 on h2.pid = p2.id
where
dt2.result = 'UN'
and dt2.CollectionDate between '11-01-2011' and '10-31-2012'
and p2.DrugCourtType = 'AD'
) as derived
on dt.pid = derived.pid
and convert(varchar, dt.CollectionDate, 101) = convert(varchar, derived.CollectionDate, 101)
group by
c.desc, dt.pid, p.id, dt.id, bio.fullname, dt.CollectionDate, dtt.desc, dt.result
order by
c.desc ASC, Participant ASC, dt.CollectionDate ASC
This is a little complicated because the your query has a separate row for each test. You need to use window/analytic functions to get the information you want. These allow you to do calculate aggregation functions, but to put the values on each line.
The following query starts with your query. It then calculates the number of UN results on each date for each participant and the total number of tests. It applies the appropriate filter to get what you want:
with base as (<your query here>)
select b.*
from (select b.*,
sum(isUN) over (partition by Participant, CollectionDate) as NumUNs,
count(*) over (partition by Partitipant, CollectionDate) as NumTests
from (select b.*,
(case when result = 'UN' then 1 else 0 end) as IsUN
from base
) b
) b
where NumUNs <> 1 or NumTests <> 1
Without the with clause or window functions, you can create a particularly ugly query to do the same thing:
select b.*
from (<your query>) b join
(select Participant, CollectionDate, count(*) as NumTests,
sum(case when result = 'UN' then 1 else 0 end) as NumUNs
from (<your query>) b
group by Participant, CollectionDate
) bsum
on b.Participant = bsum.Participant and
b.CollectionDate = bsum.CollectionDate
where NumUNs <> 1 or NumTests <> 1
If I understand the problem, the basic pattern for this sort of query is simply to include negating or exclusionary conditions in your join. I.E., self-join where columnA matches, but columns B and C do not:
select
[columns]
from
table t1
join table t2 on (
t1.NonPkId = t2.NonPkId
and t1.PkId != t2.PkId
and t1.category != t2.category
)
Put the conditions in the WHERE clause if it benchmarks better:
select
[columns]
from
table t1
join table t2 on (
t1.NonPkId = t2.NonPkId
)
where
t1.PkId != t2.PkId
and t1.category != t2.category
And it's often easiest to start with the self-join, treating it as a "base table" on which to join all related information:
select
[columns]
from
(select
[columns]
from
table t1
join table t2 on (
t1.NonPkId = t2.NonPkId
)
where
t1.PkId != t2.PkId
and t1.category != t2.category
) bt
join [othertable] on (<whatever>)
join [othertable] on (<whatever>)
join [othertable] on (<whatever>)
This can allow you to focus on getting that self-join right, without interference from other tables.