Related
I need to get my data set as this table
I am trying to get eligible set like this, need to group_concat pinged set also
x.id IN (SELECT MAX(x.id) FROM x WHERE ping rider id IS NULL GROUP BY orderId)
You can assign a group based on the cumulative number of non-null values in eligible_riders. Then aggregate and take the last value:
select og.*
from (select order_id, grp, max(eligible_riders) as eligible_riders,
group_concat(rider_id) as riders,
row_number() over (partition by order_id order by min(id) desc) as seqnum
from (select t.*,
sum(eligible_riders <> '') over (partition by order_id order by id) as grp
from t
) t
group by order_id, grp
) og
where seqnum = 1;
Hmmm . . . You could also do this with a correlated subquery, which might look a bit simpler:
select order_id, max(eligible_riders) as eligible_riders,
group_concat(rider_id) as riders
from t
where t.id >= (select max(t2.id)
from t t2
where t2.order_id = t.order_id and
t2.eligible_riders <> ''
)
group by order_id;
For performance, you want an index on (order_id, eligible_riders).
The following query executes everything:
SELECT count(entity_id), cim.institute_id, cfi.name_ FROM ci_certification_students cis INNER JOIN ci_certification_master cim ON cis.certificate_id = cim.certificate_id
INNER JOIN ci_finalized_institute cfi ON cfi.institute_id=cim.institute_id
WHERE cis.status_id=4 AND cim.institute_id is not null group by cim.institute_id order by count(entity_id) desc limit 100;
I tried the following:
SELECT seqnum,institute_id, (CASE WHEN seqnum > 9 THEN 'others' ELSE name_ END) as name_, sum(total_certi) FROM
(select count(cis.entity_id) as total_certi, cim.institute_id, cfi.name_ as certiName, ROW_NUMBER() OVER (ORDER BY COUNT(cis.entity_id) desc) as seqnum
FROM certificationdb.ci_certification_students cis
INNER JOIN ci_certification_master cim ON cis.certificate_id = cim.certificate_id
INNER JOIN certificationdb.ci_finalized_institute cfi ON cim.institute_id=cfi.institute_id
WHERE cis.status_id=4 AND cim.institute_id is not null group by cim.institute_id ORDER BY
count(cis.entity_id)desc)c GROUP BY (CASE WHEN seqnum> 9 THEN 'others' ELSE name_ END)
ORDER BY seqnum;
Any help would be appreciated...
Use row_number() and two levels of aggregation:
SELECT (CASE WHEN seqnum < 10 THEN institute_id END) as institute_id,
(CASE WHEN seqnum < 10 THEN name_ ELSE 'OTHERS' END) as name,
SUM(cnt) as cnt
FROM (SELECT cim.institute_id, cfi.name_, COUNT(*) as cnt,
ROW_NUMBER() OVER (ORDER BY COUNT(*) DESC) as seqnum
FROM ci_certification_students cis INNER JOIN
ci_certification_master cim
ON cis.certificate_id = cim.certificate_id INNER JOIN
ci_finalized_institute cfi ON
cfi.institute_id = cim.institute_id
WHERE cis.status_id = 4 AND cim.institute_id is not null
GROUP BY cim.institute_id, cfi.name_
) c
GROUP BY institute_id, name
ORDER BY MIN(seqnum);
Hi below is my sql query as
SELECT
o.OrderNumber,
oi.Sku,
Sum(Isnull(oi.Price * oi.Quantity,0)) as Price,
DENSE_RANK() over(partition by o.orderNumber order by oi.sku) as CouponRowId
from ac_OrderItems oi
inner join ac_Orders o on oi.OrderId = o.OrderId
Inner Join ac_OrderShipments os on oi.OrderShipmentId =os.OrderShipmentId
WHERE (oi.OrderItemTypeId IN (5))
group by o.OrderNumber, oi.Sku
and below is the record I am getting
OrderNumber Sku Price CouponRowId
90061 BLACKBERRY -5.6900 1
90061 LEMON -5.6900 2
90061 PEACH -5.6900 3
90061 SHIP100 -10.920 4
but I want my record as
OrderNumber Sku Price
90061 BLACKBERRY -5.6900
LEMON -5.6900
PEACH -5.6900
SHIP100 -10.920
I want that if order number is same in that case all detail record should come in 1st row and then after other record should only show Sku and price only and also we need to remove the DENSE_RANK() column
By seeing the query seems like Partition Clause can help you to
resolve the issue. Please look at the below query. I am not so sure
about the data model, but looks like you need to partition by using
the OrderNumber column. Please replace the query in the first CTE with your actual table which will be like the second query. I cant test it since I don't have the environment. Please test the query
;WITH CTE_Table
AS
(
SELECT 90061 'OrderNumber' , 'BLACKBERRY' Sku, -5.6900 'Price', 1 'CouponRowId' UNION
SELECT 90061, 'LEMON', -5.6900, 2 UNION
SELECT 90061, 'PEACH', -5.6900, 3 UNION
SELECT 90061, 'SHIP100', -10.920, 4 UNION
SELECT 90062 'OrderNumber' , 'BLACKBERRY' Sku, -5.6900 'Price', 1 'CouponRowId' UNION
SELECT 90062, 'LEMON', -5.6900, 2 UNION
SELECT 90062, 'PEACH', -5.6900, 3 UNION
SELECT 90062, 'SHIP100', -10.920, 4
),
CTE_New
AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY OrderNumber ORDER BY OrderNumber) Patrn FROM CTE_Table
)
SELECT CASE WHEN Patrn =1 THEN CONVERT(VARCHAR(10),OrderNumber) ELSE '' END OrderNumber, Sku, Price, CouponRowId FROM CTE_New
;WITH CTE_Table
AS
(
SELECT
o.OrderNumber,
oi.Sku,
Sum(Isnull(oi.Price * oi.Quantity,0)) as Price,
DENSE_RANK() over(partition by o.orderNumber order by oi.sku) as CouponRowId
from ac_OrderItems oi
inner join ac_Orders o on oi.OrderId = o.OrderId
Inner Join ac_OrderShipments os on oi.OrderShipmentId =os.OrderShipmentId
WHERE (oi.OrderItemTypeId IN (5))
group by o.OrderNumber, oi.Sku
),
CTE_New
AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY OrderNumber ORDER BY OrderNumber) Patrn FROM CTE_Table
)
SELECT CASE WHEN Patrn =1 THEN CONVERT(VARCHAR(10),OrderNumber) ELSE '' END OrderNumber, Sku, Price, CouponRowId FROM CTE_New
Seeing your comment this is an attempt to solve it on the query itself (I assumed CouponRowID might do the job, if OrderNumber is unique):
WITH
tmp AS (
SELECT o.OrderNumber, oi.Sku, SUM(ISNULL(oi.Price * oi.Quantity, 0)) AS Price, DENSE_RANK() OVER (PARTITION BY o.orderNumber ORDER BY oi.sku) AS CouponRowId
FROM ac_OrderItems oi
INNER JOIN ac_Orders o ON oi.OrderId=o.OrderId
INNER JOIN ac_OrderShipments os ON oi.OrderShipmentId=os.OrderShipmentId
WHERE(oi.OrderItemTypeId IN (5))
GROUP BY o.OrderNumber, oi.Sku
)
SELECT CASE WHEN tmp.CouponRowId=1 THEN tmp.OrderNumber END AS OrderNumber, tmp.Sku, tmp.Price
FROM tmp
ORDER BY tmp.OrderNumber, tmp.SKu;
Sorry....! I cant understand your explanations..
I just worked only for get your expected OP...
create table #ac_OrderItems(id varchar(20) --varchar, i used instead of int.Beside, varchar is easy to change to int.
, Sku varchar(20), Price decimal, CouponRowId int)
insert into #ac_OrderItems values(
90061 , 'BLACKBERRY' , -5.6900 , 1)
,(90061, 'LEMON', -5.6900, 2 )
,(90061, 'PEACH', -5.6900, 3 )
,(90061, 'SHIP100', -10.920, 4 )
,(90062 , 'BLACKBERRY' ,-5.6900 , 1 )
,(90062, 'LEMON', -5.6900, 2 )
,(90062, 'PEACH', -5.6900, 3 )
,(90062, 'SHIP100', -10.920, 4)
select * from #ac_OrderItems
;with
orders(id, sku, price, couponId, rn)
as
(
select *, ROW_NUMBER() over(partition by id order by id) from #ac_OrderItems
)select iif(rn = 1,id,''),sku,price,couponId from orders
-- if i used int, empty is denoted by 0. But you want '' this. So i used varchar id
let you know me, what you got.
I am looking for queries, using which I can analyze a general employee database. This is for Data Analysis.
Tried this for monthly employee trend
SELECT
dt.FullDateAlternateKey as 'Date'
, count(1) as ActiveCount
FROM DimDate dt
LEFT JOIN (SELECT 'Active' as 'EmpStatus', * FROM DimEmployee) emp
-- regular active employees
ON (dt.FullDateAlternateKey between emp.StartDate and ISNULL(emp.EndDate,'9999-12-31'))
WHERE
dt.FullDateAlternateKey = EOMONTH(dt.FullDateAlternateKey)
GROUP BY
dt.FullDateAlternateKey
ORDER BY
1;
also found CTE use for finding employee hierarchy
WITH DirectReports (ManagerID, EmployeeID, Title, DeptID, Level)
AS
(
-- Anchor member definition
SELECT e.ParentEmployeeKey, e.EmployeeKey, e.Title, e.DepartmentName,
0 AS Level
FROM DimEmployee AS e
WHERE e.ParentEmployeeKey IS NULL
UNION ALL
-- Recursive member definition
SELECT e.ParentEmployeeKey, e.EmployeeKey, e.Title, e.DepartmentName,
Level + 1
FROM DimEmployee AS e
INNER JOIN DirectReports AS d
ON e.ParentEmployeeKey = d.EmployeeID
)
-- Statement that executes the CTE
SELECT ManagerID, EmployeeID, Title, DeptID, Level
FROM DirectReports
WHERE DeptID = 'Information Services' OR Level = 0
also, some good queries to analyze the sales data
-- Show each sales average for Group, Country, and Region all in one query
SELECT DISTINCT
t.SalesTerritoryGroup
, t.SalesTerritoryCountry
, t.SalesTerritoryRegion
, AVG(s.SalesAmount) OVER(PARTITION BY t.SalesTerritoryGroup ) as 'GroupAvgSales'
, AVG(s.SalesAmount) OVER(PARTITION BY t.SalesTerritoryCountry ) as 'CountryAvgSales'
, AVG(s.SalesAmount) OVER(PARTITION BY t.SalesTerritoryRegion ) as 'RegionAvgSales'
FROM FactInternetSales s
JOIN DimSalesTerritory t ON
s.SalesTerritoryKey = t.SalesTerritoryKey
WHERE
YEAR(s.OrderDate) = 2013
ORDER BY
1,2,3
Use additional aggregations to understand more about product sales such as the distribution of sales etc..
SELECT
cat.EnglishProductCategoryName 'Category'
, sub.EnglishProductSubcategoryName 'SubCategory'
, count(1) 'Count' -- How many sales where there?
, sum(s.SalesAmount) 'Sales' -- How much sales did we have?
, avg(s.SalesAmount) 'Avg_SalesAmount' -- What was the Avg sale amount?
, min(s.SalesAmount) 'Min_SaleAmount' -- What was the Min sale amount?
, max(s.SalesAmount) 'Max_SaleAmount' -- What was the Max sale amount
FROM FactInternetSales s
LEFT JOIN DimProduct p ON s.ProductKey = p.ProductKey
LEFT JOIN DimProductSubcategory sub ON p.ProductSubcategoryKey = sub.ProductSubcategoryKey
LEFT JOIN DimProductCategory cat ON sub.ProductCategoryKey = cat.ProductCategoryKey
-- must use group by in order for aggregation to work properly
GROUP BY
cat.EnglishProductCategoryName -- column aliases aren't allowed
, sub.EnglishProductSubcategoryName
ORDER BY
cat.EnglishProductCategoryName
, sub.EnglishProductSubcategoryName
-- Calculate the customer acquisition funnel
SELECT
c.FirstName
, c.LastName
, c.DateFirstPurchase
, DATEDIFF(d,c.DateFirstPurchase,getdate()) as 'DaysSinceFirstPurchase' -- How long have they been a customer?
FROM DimCustomer c
ORDER BY 3 DESC
-- Calculate a Monthly average of customer tenure
SELECT
EOMONTH(c.DateFirstPurchase) as 'MonthOfFirstPurchase' -- What month did they become a customer?
, DATEDIFF(d,EOMONTH(c.DateFirstPurchase),getdate()) as 'DaysSinceFirstPurchase' -- How long have they been a customer?
, COUNT(1) as 'CustomerCount' -- How manY customers are there for this month?
FROM DimCustomer c
GROUP BY EOMONTH(c.DateFirstPurchase)
ORDER BY 2 DESC
-- Show the top product Sub Categories for each year
SELECT
count(DISTINCT s.SalesOrderNumber) 'OrderCount' -- use 1 instead of a field for faster performance
, RANK() OVER (PARTITION BY YEAR(s.OrderDate) ORDER BY sum(s.SalesAmount) DESC) 'SalesRank'
, sum(s.SalesAmount) 'TotalSales'
, cat.EnglishProductCategoryName 'Category'
, sub.EnglishProductSubcategoryName 'SubCategory'
, YEAR(s.OrderDate) 'Year'
FROM FactInternetSales s
INNER JOIN DimProduct p ON s.ProductKey = p.ProductKey
INNER JOIN DimProductSubcategory sub ON p.ProductSubcategoryKey = sub.ProductSubcategoryKey
INNER JOIN DimProductCategory cat ON sub.ProductCategoryKey = cat.ProductCategoryKey
-- must use group by in order for aggregation to work properly
GROUP BY
cat.EnglishProductCategoryName -- column aliases aren't allowed
, sub.EnglishProductSubcategoryName
, YEAR(s.OrderDate)
ORDER BY YEAR(s.OrderDate), SUM(s.SalesAmount) DESC;
-- first, create weekly sales totals
SELECT SUM(s.SalesAmount) 'WeeklySales'
, DATEPART(ww, s.OrderDate) as 'WeekNum'
FROM FactInternetSales s
WHERE YEAR(s.OrderDate) = 2013
GROUP BY
DATEPART(ww, s.OrderDate)
ORDER BY
DATEPART(ww, s.OrderDate) ASC
-- use that subquery as our source and calculate the moving average
SELECT
AVG(WeeklySales) OVER (ORDER BY WeekNum ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) as AvgSales
, WeeklySales as 'TotalSales'
, WeekNum
FROM (
SELECT SUM(s.SalesAmount) 'WeeklySales'
, DATEPART(ww, s.OrderDate) as 'WeekNum'
FROM FactInternetSales s
WHERE YEAR(s.OrderDate) = 2013
GROUP BY
DATEPART(ww, s.OrderDate)
) AS s
GROUP BY
WeekNum, WeeklySales
ORDER BY
WeekNum ASC
-- Running Total
SELECT
SUM(MonthlySales) OVER (PARTITION BY SalesYear ORDER BY SalesMonth ROWS UNBOUNDED PRECEDING) as YTDSales
, MonthlySales as 'MonthlySales'
, SalesYear
, SalesMonth
FROM (
SELECT SUM(s.SalesAmount) 'MonthlySales'
, MONTH(s.OrderDate) as 'SalesMonth'
, year(s.OrderDate) as 'SalesYear'
FROM FactInternetSales s
GROUP BY
MONTH(s.OrderDate)
, year(s.OrderDate)
) AS s
GROUP BY
SalesMonth, SalesYear, MonthlySales
ORDER BY
SalesYear, SalesMonth ASC
-- Get Prev Year Sales
WITH MonthlySales (YearNum, MonthNum, Sales)
AS
(
SELECT d.CalendarYear, d.MonthNumberOfYear, SUM(s.SalesAmount)
FROM DimDate d
JOIN FactInternetSales s ON d.DateKey = s.OrderDateKey
GROUP BY d.CalendarYear, d.MonthNumberOfYear
)
-- Get Current Year and join to CTE for previous year
SELECT
d.CalendarYear
, d.MonthNumberOfYear
, ms.Sales PrevSales
, SUM(s.SalesAmount) CurrentSales
FROM DimDate d
JOIN FactInternetSales s ON d.DateKey = s.OrderDateKey
JOIN MonthlySales ms ON
d.CalendarYear-1 = ms.YearNum AND
d.MonthNumberOfYear = ms.MonthNum
GROUP BY
d.CalendarYear
, d.MonthNumberOfYear
, ms.Sales
ORDER BY
1 DESC, 2 DESC
-- Now calculate the % change Year over Year
WITH MonthlySales (YearNum, MonthNum, Sales)
AS
(
SELECT d.CalendarYear, d.MonthNumberOfYear, SUM(s.SalesAmount)
FROM DimDate d
JOIN FactInternetSales s ON d.DateKey = s.OrderDateKey
GROUP BY d.CalendarYear, d.MonthNumberOfYear
)
-- Get Current Year and join to CTE for previous year
SELECT
d.CalendarYear
, d.MonthNumberOfYear
, ms.Sales PrevSales
, SUM(s.SalesAmount) CurrentSales
, (SUM(s.SalesAmount) - ms.Sales) / SUM(s.SalesAmount) 'PctGrowth'
FROM DimDate d
JOIN FactInternetSales s ON d.DateKey = s.OrderDateKey
JOIN MonthlySales ms ON
d.CalendarYear-1 = ms.YearNum AND
d.MonthNumberOfYear = ms.MonthNum
GROUP BY
d.CalendarYear
, d.MonthNumberOfYear
, ms.Sales
ORDER BY
1 DESC, 2 DESC
I have a query which works great for 1000 records or less but now I need to optimize it for 50,000+ records and when I run it on that it just stalls...
Here is my code:
SELECT
b1.account_num,b1.effective_date as ed1,b1.amount as am1,
b2.effective_date as ed2,b2.amount as am2
FROM bill b1
left join bill b2 on (b1.account_num=b2.account_num)
where b1.effective_date = (select max(effective_date) from bill where account_num = b1.account_num)
and (b2.effective_date = (select max(effective_date) from bill where account_num = b1.account_num and effective_date < (select max(effective_date) from bill where account_num = b1.account_num)) or b2.effective_date is null)
ORDER BY b1.effective_date DESC
My objective is to get the latest two effective dates and amounts from one table with many records.
Here is a working answer from your SQL-Fiddle baseline
First, the inner preQuery gets the max date per account. That is then joined to the bill table per account AND the effective date is less than the max already detected.
That is then joined to each respective bill for their amounts.
select
FB1.account_num,
FB1.effective_date as ed1,
FB1.amount as am1,
FB2.effective_date as ed2,
FB2.amount as am2
from
( select
pq1.account_num,
pq1.latestBill,
max( b2.effective_date ) as secondLastBill
from
( SELECT
b1.account_num,
max( b1.effective_date ) latestBill
from
bill b1
group by
b1.account_num ) pq1
LEFT JOIN bill b2
on pq1.account_num = b2.account_num
AND b2.effective_date < pq1.latestBill
group by
pq1.account_num ) Final
JOIN Bill FB1
on Final.Account_Num = FB1.Account_Num
AND Final.LatestBill = FB1.Effective_Date
LEFT JOIN Bill FB2
on Final.Account_Num = FB2.Account_Num
AND Final.secondLastBill = FB2.Effective_Date
ORDER BY
Final.latestBill DESC
In mysql , window analytic function like row_number is not there, so we can simulate the same using variables.
The good thing is, the table is scanned only once with this approach.
A row_number is assigned to each partition which is divided based on ( account number, effective date ) and only 2 rows are selected from each partition.
select account_num,
max(case when row_number =1 then effective_date end) as ed1,
max(case when row_number =1 then amount end) as am1,
max(case when row_number =2 then effective_date end) as ed2,
max(case when row_number =2 then amount end )as am2
from (
select account_num, effective_date, amount,
#num := if(#prevacct= account_num , #num + 1, 1) as row_number,
#prevacct := account_num as dummy
from bill, (select #num:=0, #prevacct := '' ) as var
order by account_num , effective_date desc
)T
where row_number <=2
group by account_num