Print result from 2 queries in different columns of one table - sql

I am trying to output result from 2 queries in one table but no luck. Tried with UNION and with this template
SELECT x.a, y.b FROM (SELECT * from a) as x, (SELECT * FROM b) as y
with no luck. My queries are:
Select
Sum('.MAIN_DB_PREFIX.'facturedet.qty) As qty_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid,
'.MAIN_DB_PREFIX.'facture.datef,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facturedet
Inner Join
'.MAIN_DB_PREFIX.'facture On '.MAIN_DB_PREFIX.'facturedet.fk_facture = '.MAIN_DB_PREFIX.'facture.rowid Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
ORDER BY
qty_sum DESC
and
Select
Sum('.MAIN_DB_PREFIX.'facture.total) As total_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid,
'.MAIN_DB_PREFIX.'facture.datef,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facture Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
ORDER BY
total_sum DESC
With both UNION or combined query as mentioned above, I get blank result and no errors.
Also, I cannot wrap the select in brackets and use an alias like (query) a UNION (query2) b as this also brings blank output.
I can output first name + last name in column one of a table, sum_qty on second, some calculation is made based on the qty and it goes in the third column. In the fourth column, I need to output total_sum
Digged here like 20 threads and tried different solutions but no result.
Full code: https://pastebin.com/bie0LXH9

This should achieve the desired result (ie. the resultset that you need to output your table) using the UNION that you were attempting (although a more efficient query could possibly be achieved using a Common Table Expression - which may or may not be available to you, depending on your RDBMS, and the version thereof).
SELECT
firstname,
lastname,
rowid,
SUM(IFNULL(qty_sum, 0)) AS qty_sum,
SUM(IFNULL(total_sum, 0)) AS total_sum
FROM
(
Select
Sum('.MAIN_DB_PREFIX.'facturedet.qty) As qty_sum,
0 AS total_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facturedet
Inner Join
'.MAIN_DB_PREFIX.'facture On '.MAIN_DB_PREFIX.'facturedet.fk_facture = '.MAIN_DB_PREFIX.'facture.rowid Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
UNION ALL
Select
0 AS qty_sum,
Sum('.MAIN_DB_PREFIX.'facture.total) As total_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facture Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
) AS tbl_all
GROUP BY rowid
ORDER BY
total_sum DESC

Related

Combine two queries to get the data in two columns

SELECT
tblEmployeeMaster.TeamName, SUM(tblData.Quantity) AS 'TotalQuantity'
FROM
tblData
INNER JOIN
tblEmployeeMaster ON tblData.EntryByHQCode = tblEmployeeMaster.E_HQCode
INNER JOIN
tblPhotos ON tblEmployeeMaster.TeamNo = tblPhotos.TeamNo
WHERE
IsPSR = 'Y'
GROUP BY
tblPhotos.TeamSort, tblPhotos.TeamNo, tblPhotos.Data,
tblEmployeeMaster.TeamName
ORDER BY
tblPhotos.TeamSort DESC, TotalQuantity DESC
This returns
Using this statement
select TeamName, count(TeamName) AS 'Head Count'
from dbo.tblEmployeeMaster
where IsPSR = 'Y'
group by teamname
Which returns
I would like to combine these 2 queries in 1 to get the below result.
Tried union / union all but no success :(
Any help will be very much helpful.
You can simply use the sub-query as follows:
SELECT tblEmployeeMaster.TeamName, SUM(tblData.Quantity) AS 'TotalQuantity',
MAX(HEAD_COUNT) AS HEAD_COUNT, -- USE THIS VALUE FROM SUB-QUERY
CASE WHEN MAX(HEAD_COUNT) <> 0
THEN SUM(tblData.Quantity)/MAX(HEAD_COUNT)
END AS PER_MAN_CONTRIBUTION -- column asked in comment
FROM tblData INNER JOIN
tblEmployeeMaster ON tblData.EntryByHQCode = tblEmployeeMaster.E_HQCode INNER JOIN
tblPhotos ON tblEmployeeMaster.TeamNo = tblPhotos.TeamNo
-- FOLLOWING SUB-QUERY CAN BE USED
LEFT JOIN (select TeamName, count(TeamName) AS HEAD_COUNT
from dbo.tblEmployeeMaster
where IsPSR = 'Y' group by teamname) AS HC
ON HC.TeamName = tblEmployeeMaster.TeamName
where IsPSR = 'Y'
GROUP BY tblPhotos.TeamSort, tblPhotos.TeamNo, tblPhotos.Data,tblEmployeeMaster.TeamName
order by tblPhotos.TeamSort desc, TotalQuantity desc

How do I find the oldest date in Group

I have a table where I need to get the oldest date from a group and be able to return all rows. I'm finding it difficult since I need to return the system_id field.
AssignedProfsHistory MatterID EffectiveDate
1 33434-3344 08/22/2005
2 33434-3344 07/12/2004
3 33434-3344 07/12/2004
4 21122-323 12/05/2007
5 43332-986 10/18/2014
6 43332-986 03/23/2013
So in this example, the rows for systemid 2 & 3 should return because they are tied for earliest date. The row for systemid 4 should return and systemid 6 should be returned.
This is what I have so far. Because I need to include the systemid(AssignedProfHistory) I'm not getting the results I need.
SELECT aph.AssignedProfsHistory,
m.MatterID,
Min(aph.EffectiveDate) as 'EffectiveDate'
from AssignedProfsHistory aph
INNER JOIN Matters m
ON aph.Matters = m.Matters
WHERE aph.AssignedType = 'Originating'
Group by m.matters,m.matterid,aph.assignedprofshistory
order by m.MatterID
Any idea how to get the results I need?
Thank you in advance.
select AssignedProfsHistory, MatterID, EffectiveDate
from (
SELECT
aph.AssignedProfsHistory,
m.MatterID,
aph.EffectiveDate,
row_number() over(partition by m.MatterID order by aph.EffectiveDate) as rn
from AssignedProfsHistory aph
INNER JOIN Matters m ON aph.Matters = m.Matters
WHERE aph.AssignedType = 'Originating'
) t
where rn = 1;
You can use the row_number window function to assign row numbers to dates for each matterid. Because the ordering is based on the ascending EffectiveDate, rows with the oldest date get assigned 1 and you select those.
If a matterid can have multiple rows with the oldest dates, you can use rank or dense_rank to get all the rows for the oldest date.
Since you want to keep the ties, I'd do it like this:
SELECT t2.AssignedProfsHistory, m.MatterID, t2.EffectiveDate
FROM (
SELECT MatterID, MIN(EffectiveDate) med
FROM AssignedProfsHistory
WHERE AssignedType = 'Originating'
GROUP BY MatterID
) t1
INNER JOIN AssignedProfsHistory t2 ON t2.MatterID = t1.MatterID
and t2.EffectiveDate = t1.med and t2.AssignedType = 'Originating'
INNER JOIN Matters m on m.Matters = t2.Matters
ORDER BY m.MatterId
Here is an SQLFiddle without the Matters table that demonstrates it can work, no windowing functions or CTE required, though a CTE would allow you to avoid repeating the AssignedType='Originating' condition.
this should get you what you need
with cte as (
SELECT aph.AssignedProfsHistory,
m.MatterID,
aph.EffectiveDate as 'EffectiveDate'
from AssignedProfsHistory aph
INNER JOIN Matters m
ON aph.Matters = m.Matters
WHERE aph.AssignedType = 'Originating'
Group by m.matters,m.matterid,aph.assignedprofshistory
)
select
AssignedProfsHistory,
MatterID,
EffectiveDate
from
cte
join (
select
min(EffectiveDate) min_effectivedate,
MatterID
from
cte
group by
MatterID
) b on cte.EffectiveDate = b.min_effectivedate and
cte.MatterID = b.MatterID
order by AssignedProfsHistory
First take the older date and then join it with your table.
WITH OlderAPH AS (
SELECT
AssignedProfsHistory,
Matters,
MIN(EffectiveDate) OlderDate
FROM AssignedProfsHistory
WHERE AssignedType = 'Originating'
GROUP BY Matters, AssignedProfsHistory )
SELECT
O.AssignedProfsHistory, M.MatterID, O.OlderDate
FROM OlderAPH O
INNER JOIN Matters M ON O.Matters = M.Matters
ORDER BY M.MatterID

counting items that match within select statement

We have a stored procedure that executes against some fairly large tables and while joining to a larger table it is also keeping a tally of how many records match the corresponding batch_id. What I am trying to figure out is can I improve this with a function for the count or some other means? Trying to get rid of the nested SELECT COUNT(*) statement. The CCTransactions table is 1.4 million rows and the BatchItems is 6.6 million rows.
SELECT a.ItemAuthID, a.FeeAuthID, a.Batch_ID, a.ItemAuthCode,
a.FeeAuthCode, b.Amount, b.Fee,
(SELECT COUNT(*) FROM BatchItems WHERE Batch_ID = a.Batch_ID) AS BatchCount,
ItemBillDate, FeeBillDate, b.AccountNumber,
b.Itemcode, ItemAuthToken, FeeAuthToken,
cc.ItemMerchant, cc.FeeMerchant
FROM CCTransactions a WITH(NOLOCK)
INNER JOIN BatchItems b WITH(NOLOCK)
ON a.Batch_ID = b.Batch_ID
INNER JOIN CCConfig cc WITH(NOLOCK)
ON a.ClientCode = cc.ClientCode
WHERE ((ItemAuthCode > '' AND ItemBillDate IS NULL)
OR (FeeAuthCode > '' AND FeeBillDate IS NULL))
AND TransactionDate BETWEEN DATEADD(d,-7,GETDATE())
AND convert(char(20),getdate(),101) + ' ' + #Cutoff
ORDER BY TransactionDate
When your DBMS supports WIndowed Aggregate Functions you can rewrite it to
COUNT(*) OVER (PARTITION BY Batch_ID)
Of course this only returns the number of rows per Batch_ID returned by the SELECT. if the inner join results in less rows, it's not the correct number.
Then it might be more efficient (depending on your DBMS) to rewrite the Scalar Subquery to a join:
SELECT a.ItemAuthID, a.FeeAuthID, a.Batch_ID, a.ItemAuthCode,
a.FeeAuthCode, b.Amount, b.Fee,
dt.BatchCount,
ItemBillDate, FeeBillDate, b.AccountNumber,
b.Itemcode, ItemAuthToken, FeeAuthToken,
cc.ItemMerchant, cc.FeeMerchant
FROM CCTransactions a WITH(NOLOCK)
INNER JOIN BatchItems b WITH(NOLOCK)
ON a.Batch_ID = b.Batch_ID
INNER JOIN CCConfig cc WITH(NOLOCK)
ON a.ClientCode = cc.ClientCode
INNER JOIN
(
SELECT BatchCount, COUNT(*) AS BatchCount
FROM BatchItems
GROUP BY Batch_ID
) AS dt ON a.Batch_ID = dt.Batch_ID
WHERE ((ItemAuthCode > '' AND ItemBillDate IS NULL)
OR (FeeAuthCode > '' AND FeeBillDate IS NULL))
AND TransactionDate BETWEEN DATEADD(d,-7,GETDATE())
AND convert(CHAR(20),getdate(),101) + ' ' + #Cutoff
ORDER BY TransactionDate

Complex Full Outer Join

Sigh ... can anyone help? In the SQL query below, the results I get are incorrect. There are three (3) labor records in [LaborDetail]
Hours / Cost
2.75 / 50.88
2.00 / 74.00
1.25 / 34.69
There are two (2) material records in [WorkOrderInventory]
Material Cost
42.75
35.94
The issue is that the query incorrectly returns the following:
sFunction cntWO sumLaborHours sumLaborCost sumMaterialCost
ROBOT HARNESS 1 12 319.14 236.07
What am I doing wrong in the query that is causing the sums to be multiplied? The correct values are sumLaborHours = 6, sumLaborCost = 159.57, and sumMaterialCost = 78.69. Thank you for your help.
SELECT CASE WHEN COALESCE(work_orders.location, Work_Orders_Archived.location) IS NULL
THEN '' ELSE COALESCE(work_orders.location, Work_Orders_Archived.location) END AS sFunction,
(SELECT COUNT(*)
FROM work_orders
FULL OUTER JOIN Work_Orders_Archived
ON work_orders.order_number = Work_Orders_Archived.order_number
WHERE COALESCE(work_orders.order_number, Work_Orders_Archived.order_number) = '919630') AS cntWO,
SUM(Laborhours) AS sumLaborHours,
SUM(LaborCost) AS sumLaborCost,
SUM(MaterialCost*MaterialQuanity) AS sumMaterialCost
FROM work_orders
FULL OUTER JOIN Work_Orders_Archived
ON work_orders.order_number = Work_Orders_Archived.order_number
LEFT OUTER JOIN
(SELECT HoursWorked AS Laborhours, TotalDollars AS LaborCost, WorkOrderNo
FROM LaborDetail) AS LD
ON COALESCE(work_orders.order_number, Work_Orders_Archived.order_number) = LD.WorkOrderNo
LEFT OUTER JOIN
(SELECT UnitCost AS MaterialCost, Qty AS MaterialQuanity, OrderNumber
FROM WorkOrderInventory) AS WOI
ON COALESCE(work_orders.order_number, Work_Orders_Archived.order_number) = WOI.OrderNumber
WHERE COALESCE(work_orders.order_number, Work_Orders_Archived.order_number) = '919630'
GROUP BY CASE WHEN COALESCE(work_orders.location, Work_Orders_Archived.location) IS NULL
THEN '' ELSE COALESCE(work_orders.location, Work_Orders_Archived.location) END
ORDER BY sFunction
Try using the SUM function inside a derived table subquery when doing the full join to "WorkOrderInventory" like so...
select
...
sum(hrs) as sumlaborhrs,
sum(cost) as sumlaborcost,
-- calculate material cost in subquery
summaterialcost
from labordetail a
full outer join
(select ordernumber, sum(materialcost) as summaterialcost
from WorkOrderInventory
group by ordernumber
) b on a.workorderno = b.ordernumber
i created a simple sql fiddle to demonstrate this (i simplified your query for examples sake)
Looks to me that work_orders and work_orders_archived contains the same thing and you need both tables as if they were one table. So you could instead of joining create a UNION and use it as if it was one table:
select location as sfunction
from
(select location
from work_orders
union location
from work_orders_archived)
Then you use it to join the rest. What DBMS are you on? You could use WITH. But this does not exist on MYSQL.
with wo as
(select location as sfunction, order_number
from work_orders
union location, order_number
from work_orders_archived)
select sfunction,
count(*)
SUM(Laborhours) AS sumLaborHours,
SUM(LaborCost) AS sumLaborCost,
SUM(MaterialCost*MaterialQuanity) AS sumMaterialCost
from wo
LEFT OUTER JOIN
(SELECT HoursWorked AS Laborhours, TotalDollars AS LaborCost, WorkOrderNo
FROM LaborDetail) AS LD
ON COALESCE(work_orders.order_number, Work_Orders_Archived.order_number) = LD.WorkOrderNo
LEFT OUTER JOIN
(SELECT UnitCost AS MaterialCost, Qty AS MaterialQuanity, OrderNumber
FROM WorkOrderInventory) AS WOI
ON COALESCE(work_orders.order_number, Work_Orders_Archived.order_number) = WOI.OrderNumber
where wo.order_number = '919630'
group by sfunction
order by sfunction
The best guess is that the work orders appear more than once in one of the tables. Try these queries to check for duplicates in the two most obvious candidate tables:
select cnt, COUNT(*), MIN(order_number), MAX(order_number)
from (select order_number, COUNT(*) as cnt
from work_orders
group by order_number
) t
group by cnt
order by 1;
select cnt, COUNT(*), MIN(order_number), MAX(order_number)
from (select order_number, COUNT(*) as cnt
from work_orders_archived
group by order_number
) t
group by cnt
order by 1;
If either returns a row where cnt is not 1, then you have duplicates in the tables.

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.