I am having one order table which is containing the orders.
Each order is having specific cost related to it and also status of the order.
So i need 4 columns in the output.
1st will show count of the records having status id as 1 & 2.
2nd will show sum of cost of the records having status id as 1 & 2
3rd will show count of the records having status id not in 1 & 2.
4th will show sum of cost of the records having status id not in 1 & 2.
I am not getting the approach how to fix such issue so that i don't need to hit the database many times.Any solution
If I understand correctly, I have a simple example for your case.
You could use SUM and CASE WHEN to achieve it.
Hope it helps.
DECLARE #SampleData AS TABLE
(
Id int IDENTITY (1,1),
StatusId int,
Cost decimal(10,2)
)
INSERT INTO #SampleData
(
--Id - this column value is auto-generated
StatusId,
Cost
)
VALUES
(1, 10),(2, 10),(3, 20), (4, 20),
(1, 10),(2, 10),(3, 20), (4, 20),
(1, 10),(2, 10),(3, 20), (4, 20)
SELECT
sum(CASE WHEN sd.StatusId IN (1,2) THEN 1 ELSE 0 END) AS TotalCount_1_2,
sum(CASE WHEN sd.StatusId IN (1,2) THEN sd.Cost ELSE 0 END) AS TotalCost_1_2,
sum(CASE WHEN sd.StatusId NOT IN (1,2) THEN 1 ELSE 0 END) AS TotalCount_Not_in_1_2,
sum(CASE WHEN sd.StatusId NOT IN (1,2) THEN sd.Cost ELSE 0 END) TotalCost_Not_in_1_2
FROM #SampleData sd
Returns
TotalCount_1_2 TotalCost_1_2 TotalCount_Not_in_1_2 TotalCost_Not_in_1_2
----------------------------------------------------------------------------
6 60.00 6 120.00
Do you want this.
SELECT COUNT(f1) AS Col1
,SUM(f1) AS Col2
,(SELECT COUNT(f1) FROM yourTable t2 WHERE t1.id1 <> t2.id1 OR t1.id2 <> t2.id2) AS Col3
,(SELECT SUM(f1) FROM yourTable t3 WHERE t1.id1 <> t3.id1 OR t1.id2 <> t3.id2) AS Col4
FROM yourTable t1
GROUP BY id1,id2
Related
Here's the output I'm hoping to achieve:
I'd like to start with the most recent ReportMonth working backwards and start a new partition every time there's a MonthsBetween > 2. I'd like to avoid loops if possible.
EDIT: Here's the create statement for the table
CREATE TABLE #temp (
MonthsBetween int,
ReportMonth date)
INSERT INTO #temp VALUES(0, '2019-12-01')
INSERT INTO #temp VALUES(1, '2019-11-01')
INSERT INTO #temp VALUES(1, '2019-10-01')
INSERT INTO #temp VALUES(3, '2019-07-01')
INSERT INTO #temp VALUES(1, '2019-06-01')
INSERT INTO #temp VALUES(3, '2019-03-01')
You may try with the following approach using LAG() and windowed SUM():
Statement (for groups based on difference between each two values for MonthsBetween > 2):
SELECT
MonthsBetween,
ReportMonth,
SUM(GroupID) OVER (ORDER BY ReportMonth DESC) AS PartitionID
FROM (
SELECT
*,
CASE
WHEN LAG(MonthsBetween) OVER (ORDER BY ReportMonth DESC) IS NULL THEN 1
WHEN MonthsBetween - LAG(MonthsBetween) OVER (ORDER BY ReportMonth DESC) >= 2 THEN 1
ELSE 0
END AS GroupId
FROM #temp
) cte
Statement (for groups based on value for MonthsBetween > 2):
SELECT
MonthsBetween,
ReportMonth,
SUM(CASE WHEN MonthsBetween > 2 THEN 1 ELSE 0 END) OVER (ORDER BY ReportMonth DESC) + 1 AS PartitionID
FROM #temp
Result:
MonthsBetween ReportMonth PartitionID
0 2019-12-01 1
1 2019-11-01 1
1 2019-10-01 1
3 2019-07-01 2
1 2019-06-01 2
3 2019-03-01 3
Looks like your MonthsBetween uses a Lag or Lead function already(or precalculated)
create table #temp (
MonthsBetween int null,
ReportMonth date null
)
insert into #temp (MonthsBetween,ReportMonth)
Values ('0','2019-12-01'),
('1','2019-11-01'),
('1','2019-10-01'),
('3','2019-07-01'),
('1','2019-06-01'),
('3','2019-03-01')
select t.*,
sum(case when MonthsBetween <= 2 then 0 else 1 end) over (order by t.[ReportMonth] DESC) +1 as [PartitionID]
from #temp t
I am trying to get some sorting and keep together (not really grouping) working.
In my sample data I would like to keep the DealerIDs together, sorted by IsPrimaryDealer DESC, but show the group (ok maybe it is grouping) of dealers by the ones with the most recent entry.
Result set 2 is the closest, but Grant and his brother should be displayed as the first two rows, in that order. (Grant should be row 1, Grants Brother row 2 because Grants Brother was the most recently added)
DECLARE #temp TABLE (
DealerPK int not null IDENTITY(1,1), DealerID int,
IsPrimaryDealer bit, DealerName varchar(50), DateAdded datetime
)
INSERT INTO #temp VALUES
(1, 1, 'Bob', GETDATE() - 7),
(2, 1, 'Robert', GETDATE() - 7),
(3, 1, 'Grant', GETDATE() - 7),
(3, 0, 'Grants Brother', GETDATE() - 1),
(2, 0, 'Roberts Nephew', GETDATE() - 2),
(1, 0, 'Bobs Cousin', GETDATE() - 3)
-- Data As Entered
SELECT * FROM #temp
-- Data Attempt at Row Numbering
SELECT *, intPosition =
ROW_NUMBER() OVER (PARTITION BY IsPrimaryDealer ORDER BY DealerID, IsPrimaryDealer DESC)
FROM #temp
ORDER BY DateAdded DESC
-- Data Attempt By DateAdded
SELECT *, intPosition =
ROW_NUMBER() OVER (PARTITION BY DealerID ORDER BY DateAdded DESC)
FROM #temp
ORDER BY intPosition, DateAdded
Expected Result
PK DID IsPr Name DateAdded
3 3 1 Grant 2015-10-08 17:14:26.497
4 3 0 Grants Brother 2015-10-14 17:14:26.497
2 2 1 Robert 2015-10-08 17:14:26.497
5 2 0 Roberts Nephew 2015-10-13 17:14:26.497
1 1 1 Bob 2015-10-08 17:14:26.497
6 1 0 Bobs Cousin 2015-10-12 17:14:26.497
As requested by OP:
;WITH Cte AS(
SELECT *,
mx = MAX(DateAdded) OVER(PARTITION BY DealerID) FROM #temp
)
SELECT *
FROM Cte
ORDER BY mx DESC, DealerID, IsPrimaryDealer DESC
Hope i understood your question,
This query results expected output :
SELECT Row_number()
OVER (
PARTITION BY DealerID
ORDER BY DealerPK)RN,
DealerPK,
DealerID,
IsPrimaryDealer,
DealerName,
DateAdded
FROM #temp
ORDER BY DealerID DESC
I have two table like
ItemTable_One
id itemID Date qty
===================================================
1 1 2015-07-1 10
2 1 2015-07-3 20
3 2 2015-07-5 30
4 2 2015-07-7 40
ItemTable_Two
id itemID Date qty
===================================================
1 1 2015-07-2 50
2 1 2015-07-4 60
3 3 2015-07-6 70
4 3 2015-07-8 80
I want to retrieve data where itemID is equal to 1 in a date range.
For example ( date range between 2015-07-1 and 2015-07-30 )
itemID Date ItemTableOne_qty ItemTableTwo_qty
============================================================================
1 2015-07-1 10 0
1 2015-07-3 20 0
1 2015-07-2 0 50
1 2015-07-4 0 60
I've tried union join and subquery to do it, but I'm very weak in sql query.
You can use UNION ALL to get all the data you need:
SELECT ItemTable_One.itemID, ItemTable_One.Date, ItemTable_One.qty as ItemTableOne_qty, 0 as ItemTableTwo_qty
FROM ItemTable_One
WHERE ItemTable_One.itemID = 1 AND
ItemTable_One.Date BETWEEN '2015-07-01' AND '2015-08-01'
UNION ALL
SELECT ItemTable_Two.itemID, ItemTable_Two.Date, 0 as ItemTableOne_qty, ItemTable_Two.qty as ItemTableTwo_qty
FROM ItemTable_One
WHERE ItemTable_Two.itemID = 1 AND
ItemTable_Two.Date BETWEEN '2015-07-01' AND '2015-08-01'
You can use a FULL OUTER JOIN:
SELECT COALESCE(t1.itemID, t2.itemID) AS itemID,
COALESCE(t1.[Date], t2.[Date]) AS [Date],
COALESCE(t1.qty, 0) AS ItemTableOne_qty,
COALESCE(t2.qty, 0) AS ItemTableTwo_qty
FROM ItemTable_One AS t1
FULL OUTER JOIN ItemTable_Two AS t2 ON t1.itemID = t2.itemID AND t1.[Date] = t2.[Date]
WHERE COALESCE(t1.itemID, t2.itemID) = 1 AND
COALESCE(t1.[Date], t2.[Date]) BETWEEN '2015-07-01' AND '2015-07-31'
ORDER BY COALESCE(t1.[Date], t2.[Date])
This will put records having the same [Date] value in the source tables, into the same row of the output table.
If records of ItemTable_One always have separate [Date] values from records of ItemTable_Two, then the UNION solution proposed in other answers is preferable.
Demo here
Try this:
select itemID, Date, qty as ItemTableOne_qty, 0 as ItemTableTwo_qty
from ItemTable_One
where ItemID = 1
and date >= '20150701'
and date < '20150731'
union all
select itemID, Date, 0 as ItemTableOne_qty, qty as ItemTableTwo_qty
from ItemTable_Two
where ItemID = 1
and date >= '20150701'
and date < '20150731'
The upper limit for date is intentionally < than the wanted date +1 so that in case it's a datetime that has the time in it, the last day will be included too.
You do it with a FULL JOIN or a UNION ALL (depending on exact required output)
FULL JOIN
A FULL JOIN will allow you to get results like you show as long as there are no identical dates between the 2 tables. If such dates are present in both tables, you'd get a single row per date with both values filled.
The query to use is:
SELECT COALESCE(t1.itemID, t2.itemID) itemID, COALESCE(t1.Date, t2.Date) Date,
ISNULL(t1.qty, 0) ItemTableOne_qty, ISNULL(t2.qty, 0) ItemTableTwo_qty
FROM ItemTable_One t1 FULL JOIN ItemTable_Two t2
ON t1.itemID = t2.itemID AND t1.Date = t2.Date
WHERE COALESCE(t1.itemID, t2.itemID) = 1 AND
COALESCE(t1.Date, t2.Date) BETWEEN '2015-07-01' AND '2015-08-01'
UNION ALL
A UNION ALL will allow you to get resutls like you show and will create duplicate rows where the same date exists in both tables. There will always be at least 1 '0' value in any row.
The query to use is:
SELECT itemID, Date, qty ItemTableOne_qty, 0 ItemTableTwo_qty
FROM ItemTable_One
WHERE itemID = 1 AND Date BETWEEN '2015-07-01' AND '2015-08-01'
UNION ALL
SELECT itemID, Date, 0 ItemTableOne_qty, qty ItemTableTwo_qty
FROM ItemTable_Two
WHERE itemID = 1 AND Date BETWEEN '2015-07-01' AND '2015-08-01'
this will be the other way we can achieve the same result basing on your sample data
declare #ItemTable_One table (id int, itemID int, Date date, qty int)
insert into #ItemTable_One values
(1, 1, '2015-07-1', 10),
(2, 1, '2015-07-3', 20),
(3, 2, '2015-07-5', 30),
(4, 2, '2015-07-7', 40)
declare #ItemTable_Two table (id int, itemID int, Date date, qty int)
insert into #ItemTable_Two values
(1, 1, '2015-07-2', 50),
(2, 1, '2015-07-4', 60) ,
(3, 3, '2015-07-6', 70) ,
(4, 3, '2015-07-8', 80)
;with CTE AS (
select i.itemID As ItemID1,ii.itemID As ItemID2,i.Date As Dated1,ii.Date As Dated2,i.qty as qty,ii.qty As qty1 from #ItemTable_One i
CROSS APPLY (select * from #ItemTable_Two )ii
where i.id = ii.id AND i.itemID = ii.itemID
)
select * from (
Select ItemID1 As item,Dated1 AS Date, qty,'' as qty1 from CTE
UNION
Select ItemID2 As item,Dated2 AS Date,'' as qty,qty1 from CTE)T
--ORDER BY t.qty desc ,t.qty1
Use inline view to simplify horrid sql used in prior answers:
SELECT *
FROM (
SELECT COALESCE(t1.itemID, t2.itemID) AS itemID,
COALESCE(t1.[Date], t2.[Date]) AS [Date],
COALESCE(t1.qty, 0) AS ItemTableOne_qty,
COALESCE(t2.qty, 0) AS ItemTableTwo_qty
FROM ItemTable_One AS t1 FULL OUTER JOIN ItemTable_Two AS t2
ON t1.itemID = t2.itemID AND t1.[Date] = t2.[Date]
) AS v
WHERE v.itemID = 1 AND
v.[Date] BETWEEN '2015-07-01' AND '2015-07-31'
ORDER BY v.[Date]
From this it is possible for the following :
TABLE 1
Id | final | Date
------------------
1 236 02-11-14
2 10 07-01-12
3 58 09-02-10
TABLE 2
Id | final | Date
------------------
1 330 02-11-14
2 5 07-01-12
3 100 09-02-10
ADD both Table 1 and Table 2 Sum'd values(column final), and then work out the AVG number from this and create this as another column average, THEN if table2 for example SUM'd original amount (before the AVG) is higher than Table 1 SUM'd amount create another column and print in that column 'Tbl2 has the higher amount' and vise verser if table 1 had the higher amount.
End result Column wise table would look like this :
|tb1_final_amount|tb2_final_amount|Avg_Amount|Top_Score_tbl
|tb1_final_amount|tb2_final_amount|Avg_Amount|Top_Score_tbl
304 435 369.5 tb2 has highest score
This is one way (of many) to do this. You can sum up the two tables and use them as derived tables in a query like so:
select
tb1_final_amount,
tb2_final_amount,
(tb1_final_amount+tb2_final_amount)/2.0 as Avg_Amount,
case
when tb1_final_amount < tb2_final_amount then 'tb2 has highest score'
else 'tb1 has highest score'
end as Top_Score_tbl
from
(select SUM(final) as tb1_final_amount from TABLE1) t1,
(select SUM(final) as tb2_final_amount from TABLE2) t2
This does the trick!:
--SET UP Table1
CREATE TABLE Table1 (ID INT, final INT, [Date] DATETIME)
INSERT Table1 VALUES (1, 236, '20141102')
INSERT Table1 VALUES (2, 10, '20120107')
INSERT Table1 VALUES (3, 58, '20100209')
--SET UP Table2
CREATE TABLE Table2 (ID INT, final INT, [Date] DATETIME)
INSERT Table2 VALUES (1, 330, '20141102')
INSERT Table2 VALUES (2, 5, '20120107')
INSERT Table2 VALUES (3, 100, '20100209')
-- Query
SELECT
SUM(CASE WHEN t.TableName = 'Table1' THEN T.final
ELSE 0
END) AS tb1_final_amount,
SUM(CASE WHEN t.TableName = 'Table2' THEN T.final
ELSE 0
END) AS tb2_final_amount,
AVG(T.final) AS Avg_Amount,
ISNULL((
SELECT
'Table1'
FROM
Table1 T1
WHERE
SUM(CASE WHEN t.TableName = 'Table1' THEN T.final
ELSE 0
END) > SUM(CASE WHEN t.TableName = 'Table2' THEN T.final
ELSE 0
END)
), 'Table2')
FROM
(
SELECT
'Table1' AS TableName,
final
FROM
Table1
UNION ALL
SELECT
'Table2',
final
FROM
Table2
) AS T
I have staff members that are assigned tasks, I need to find the percentage of tasks that a staff member has completed year-to-date... of those that were assigned to him. If John is assigned 10 tasks, and completed 5 I need to show John has closed .50 (50%).
I have two tables:
Tasks and Tasks_cstm
Tasks t
| ID | STATUS |Date_Completed|
The statuses are 'In Progress', 'Not Started', 'Completed'
Tasks_cst tc
| ID_C|Staff_Member|
The tables are joined on t.id = tc.id_c
This returns the number completed:
(select count(*)as Completed from tasks_CSTM tc
join tasks t
on t.id = tc.id_c
where status = 'completed'
group by staff_member_C )
This returns the total number of tasks:
(select count(*)as Total from tasks_CSTM tc
join tasks t
on t.id = tc.id_c
group by staff_member_C )
This is what I've come up with, but it errors: Subquery returned more than 1 value.
select staff_member_c,((select count(*)as Completed from tasks_CSTM tc
join tasks t
on t.id = tc.id_c
where status = 'completed'
group by staff_member_C )/(select count(*)as Total from tasks_CSTM tc
join tasks t
on t.id = tc.id_c
group by staff_member_C ))
from tasks t
join tasks_CSTM tc
on t.id = tc.id_C
group by staff_member_C
Any help is appreciated.
Something like this I think:
select staff_member_c, sum(case when status='completed' then 1.0 end)/count(*) as pctCompleted
from tasks_cstm tc
join tasks t
on t.id = tc.id_c
group by staff_member_c
You might need "else 0.0" in the case statement (but don't in MSSQL), and you might need nullif(count(*),0) in the denominator (but probably not in any DBMS).
There's a couple issues here to grapple with. One of which is dealing with the "year-to-date" part. Right now, with a Date_Completed column, there's no way to know when a task was assigned/created, which invalidates our ability to know year-to-date info. Barring that part of the question, here's my query which should work. I have a WHERE clause commented out which can easily be adapted to use a Date_Assigned column for year-to-date info.
select
staff_member
, sum(case t.status when 'Completed' then 1.0 else 0 end) [Completed]
, count(*) [Total]
, sum(case t.status when 'Completed' then 1.0 else 0 end) / count(*) [CompletedPercent]
from
tasks t
inner join tasks_cstm tc
on t.id = tc.id_C
--where
-- dateadd(year, datediff(year, 0, Date_Assigned), 0) = dateadd(year, datediff(year, 0, getdate()), 0)
group by
staff_member
And here's the setup code I used to (un-comprehensibly) test it out:
create table tasks (ID int, Status varchar(50), Date_Completed date)
create table tasks_cstm (ID_C int, Staff_Member varchar(50))
insert into tasks
select 1, 'Not Started', null
union all
select 2, 'Completed', '2011-04-15'
union all
select 3, 'In Progress', null
insert into tasks_cstm
select 1, 'Cadaeic'
union all
select 2, 'Cadaeic'
union all
select 3, 'Cadaeic'
Resulting in this:
staff_member Completed Total CompletedPercent
------------------- -------------------- ----------- -----------------------
Cadaeic 1.0 3 0.333333
-- Tasks
declare #T table(ID int, Status varchar(20))
-- Tasks_cst
declare #TC table(ID_C int, Staff_Member varchar(20))
insert into #TC values (1, 'Staff 1')
insert into #TC values (2, 'Staff 2')
insert into #TC values (3, 'Staff 3')
insert into #T values (1, 'Completed')
insert into #T values (1, 'Completed')
insert into #T values (1, 'In Progress')
insert into #T values (2, 'Completed')
insert into #T values (2, 'In Progress')
insert into #T values (3, 'In Progress')
select *
from #TC as TC
cross apply
(select sum(case T.Status when 'Completed' then 1.0 else 0.0 end) / count(*)
from #T as T
where T.ID = TC.ID_C) as C(PrecentCompleted)
Result
ID_C Staff_Member PrecentCompleted
----------- -------------------- ---------------------------------------
1 Staff 1 0.666666
2 Staff 2 0.500000
3 Staff 3 0.000000