I have a line:
sum(purchases) over(partition by category order by value_day range between interval '1' month preceding and current row)
If value_day = Aug 21, it returns sum from and included July 21 till and included Aug 21, but I need from and included July 22 till and included Aug 21.
How can I do that?
You can use an expression to define the starting point of the window. So you can
Subtract a month from the current date
Add a day to it
Giving something like:
sum ( purchases ) over (
partition by category
order by value_day
range between ( value_day - ( add_months ( value_day, -1 ) + 1 ) ) preceding
and current row
)
You can either:
Use two windowed functions, your one to add everything from the past month and then subtract a second one that just covers the range you do not want to include; or
Use a correlated sub-query rather than windowed analytic functions.
SELECT t.*,
sum(purchases) over(
partition by category
order by value_day
range between interval '1' month preceding and current row
) -
COALESCE(
sum(purchases) over(
partition by category
order by value_day
range between interval '1' month preceding and interval '1' month preceding
),
0
) AS total1,
( SELECT SUM(s.purchases)
FROM table_name s
WHERE t.category = s.category
AND ADD_MONTHS(t.value_day, -1) + INTERVAL '1' DAY <= s.value_day
AND s.value_day <= t.value_day
) AS total2
FROM table_name t;
Which, for the sample data:
CREATE TABLE table_name (category, value_day, purchases) AS
SELECT 1, DATE '2022-01-01' + LEVEL - 1, LEVEL
FROM DUAL
CONNECT BY LEVEL <= 50;
Outputs:
CATEGORY
VALUE_DAY
PURCHASES
TOTAL1
TOTAL2
...
...
...
...
...
1
01-FEB-22
32
527
527
1
02-FEB-22
33
558
558
1
03-FEB-22
34
589
589
1
04-FEB-22
35
620
620
1
05-FEB-22
36
651
651
1
06-FEB-22
37
682
682
1
07-FEB-22
38
713
713
1
08-FEB-22
39
744
744
1
09-FEB-22
40
775
775
1
10-FEB-22
41
806
806
1
11-FEB-22
42
837
837
1
12-FEB-22
43
868
868
1
13-FEB-22
44
899
899
1
14-FEB-22
45
930
930
1
15-FEB-22
46
961
961
1
16-FEB-22
47
992
992
1
17-FEB-22
48
1023
1023
1
18-FEB-22
49
1054
1054
1
19-FEB-22
50
1085
1085
db<>fiddle here
I am trying to obtain "pairs" of records and I just cant figure out.
Here is what I have:
Id TruckId LocationId MaterialMode
145223 1198 19 43
145224 1199 19 43
145225 1200 19 43
145226 1198 20 43
145227 1199 20 43
145228 1200 20 43
145229 1199 21 46
145230 1198 21 46
145231 1200 21 46
145232 1198 22 46
145233 1199 22 46
145234 1200 22 46
145235 1198 19 43
145236 1199 19 43
145237 1200 19 43
145238 1198 20 43
145239 1199 20 43
145240 1200 20 43
145241 1199 21 46
145242 1198 21 46
145243 1200 21 46
145244 1198 22 46
145245 1199 22 46
145246 1200 22 46
I need to get the following:
Id A Id B
145223 145226
145224 145227
145225 145228
145229 145233
145230 145232
145231 145234
145235 145238
145236 145239
145237 145240
145241 145245
145242 145244
145243 145246
Basically matching a TruckId between 2 locations under the same material mode
I have tried:
SELECT
Id AS IdA,
Lead(Id, 1, NULL) OVER(PARTITION BY TruckId, MaterialMode ORDER BY Date) AS IdB
FROM T
This produces:
Id A Id B
145223 145226
145224 145227
145225 145228
*145226 145235
*145227 145236
*145228 145237
145229 145233
145230 145232
145231 145234
*145232 145242
*145233 145241
*145234 145243
145235 145238
145236 145239
145237 145240
145241 145245
145242 145244
145243 145246
Records with the * I don't want them. If a pair is matched then that record should not be part of "another match"
I believe I understand your problem and below is a solution.
Explanation: I sorted the data rows into start and end points sets like in gap and islands problems and then joined a start id with end id for same material mode and truck.
; with separationSet as
(
select
*,
dense_rank()
over(
partition by materialmode,truckid
order by locationid asc
) as r
from T
)
, scoredSet as
(
select
*,
row_number()
over(
partition by materialmode,truckid,r
order by id
) as r2
from separationSet
)
, startToEndPairs as
(
select
S.id as StartId,
E.id as EndId
from scoredSet S
join scoredSet E
on S.r=1 and E.r=2
and S.r2=E.r2
and S.TruckId=E.TruckId
and S.materialmode=E.materialmode
)
select
*
from starttoEndPairs
order by StartId asc
See working demo
I want to show the date field can not group.
My Query:
SELECT DAY(T1.UI_CreateDate) AS DATEDAY, SUM(1) AS TOTALCOUNT
FROM mydb.dbo.LP_UseImpression T1 WHERE T1.UI_BR_BO_ID = 45
GROUP BY DAY(T1.UI_CreateDate)
Result:
DATEDAY TOTALCOUNT
----------- -----------
15 186
9 1
3 2
26 481
21 297
27 342
18 18
30 14
4 183
25 553
13 8
22 469
16 1
17 28
20 331
28 90
14 33
8 1
But i want to show the full date...
Example result:
DATEDAY TOTALCOUNT
----------- -----------
15/06/2015 186
9/06/2015 1
3/06/2015 2
26/06/2015 481
21/06/2015 297
27/06/2015 342
18/06/2015 18
30/06/2015 14
4/06/2015 183
25/06/2015 553
13/06/2015 8
22/06/2015 469
16/06/2015 1
17/06/2015 28
20/06/2015 331
28/06/2015 90
14/06/2015 33
8/06/2015 1
I want to see the results...
I could not get a kind of results...
How can I do?
Thanx!
How about just casting to date to remove any time component:
SELECT CAST(T1.UI_CreateDate as DATE) AS DATEDAY, COUNT(*) AS TOTALCOUNT
FROM mydb.dbo.LP_UseImpression T1
WHERE T1.UI_BR_BO_ID = 45
GROUP BY CAST(T1.UI_CreateDate as DATE)
ORDER BY DATEDAY;
SUM(1) for calculating the count does work. However, because SQL has the COUNT(*) function, it seems a bit awkward.
So you can group by DAY(T1.UI_CreateDate) or use full date for grouping. But these are different . As both these dates '2015-04-15' and '2015-12-15' result in same DAY value of 15.
Assuming you want to group on DAY rather than date please try the below version of query:
SELECT DISTINCT
T1.UI_CreateDate as DATEDAY,
count(1) over (PARTITION BY DAY(T1.UI_CreateDate) ) AS TOTALCOUNT
FROM mydb.dbo.LP_UseImpression T1 WHERE T1.UI_BR_BO_ID = 45
sql fiddle for demo: http://sqlfiddle.com/#!6/c3337/1
i have bunch of discount scheme for my item table , and for each item i have different discount scheme. now i want to give row id to that item but it should be start from zer0(0) for each item group, and when it got different DiscountId then it should be change, my table is in below image..
now for an example, for ItemCode 429 there are 7 same discount with DiscountId 427 so for this all i want row Id 0(zero) but when change DiscountId, it means for Same ItemCode and 428 DiscountId, then i want another RowId with increment. and when ItemCode change then rowId should be start from Zero(0).
can anyone help me please??
my current query is simpaly "select * from ItemDiscount_md".
Maybe something like this:
Test data:
DECLARE #tbl TABLE(ITEMCode INT,DiscountId INT)
INSERT INTO #tbl
VALUES
(73,419),(73,419),(73,420),(73,420),(73,420),
(429,427),(429,427),(429,427),(429,427),(429,427),
(429,427),(429,427),(429,427),(429,428),(429,428)
Query:
;WITH CTE
AS
(
SELECT
DENSE_RANK() OVER(PARTITION BY tbl.ITEMCode
ORDER BY DiscountId) AS Rownbr,
tbl.*
FROM
#tbl AS tbl
)
SELECT
CTE.Rownbr-1 AS RowNbr,
CTE.DiscountId,
CTE.ITEMCode
FROM
CTE
Of course you can simplify the query by writing this:
SELECT
(DENSE_RANK() OVER(PARTITION BY tbl.ITEMCode
ORDER BY DiscountId))-1 AS Rownbr,
tbl.*
FROM
#tbl AS tbl
I just thought it was nicer and more readable with a CTE function
References:
DENSE_RANK
OVER Clause
Using Common Table Expressions
ROW_NUMBER
EDIT
To answer the comment. No ROW_NUMBER will not return the same counter. This is the output with DENSE_RANK:
0 419 73
0 419 73
1 420 73
1 420 73
1 420 73
0 427 429
0 427 429
0 427 429
0 427 429
0 427 429
0 427 429
0 427 429
0 427 429
1 428 429
1 428 429
And this is with ROW_NUMBER:
0 419 73
1 419 73
2 420 73
3 420 73
4 420 73
0 427 429
1 427 429
2 427 429
3 427 429
4 427 429
5 427 429
6 427 429
7 427 429
8 428 429
9 428 429
As you see ROW_NUMBER() recounts the group when the DENSE_RANK ranks the group
Just more simplified Arion's Answer
DECLARE #tbl TABLE(ITEMCode INT,DiscountId INT)
INSERT INTO #tbl
VALUES
(73,419),
(73,419),
(73,420),
(73,420),
(73,420),
(429,427),
(429,427),
(429,427),
(429,427),
(429,427),
(429,427),
(429,427),
(429,427),
(429,428),
(429,428)
;
SELECT
(DENSE_RANK() OVER(PARTITION BY ITEMCode ORDER BY DiscountId) -1) AS Rownbr,
DiscountId,
ITEMCode
FROM
#tbl
if you got data like this: (from the image) #temp table
itemcode DiscountId DayId
----------- ----------- -----------
102 416 2
102 416 3
102 416 4
79 419 3
79 419 1
79 420 2
79 420 1
use row_number() to get below result
itemcode DiscountId DayId rowid
----------- ----------- ----------- --------------------
102 416 2 1
102 416 3 2
102 416 4 3
79 419 3 1
79 419 1 2
79 420 2 1
79 420 1 2
SQL example:
select itemcode, DiscountId, DayId
, ROW_NUMBER() over (partition by Discountid order by discountid) as 'rowid'
from #temp
Hi Here is my SQL code:
SELECT a."Date", a."Missed", b."Total Client Schedules", cast(100-((a."Missed"*100) / b."Total Client Schedules")AS decimal) as "Pct Completed" -
FROM -
( -
SELECT DATE(scheduled_start) as "Date",count(*) as "Missed" FROM -
events WHERE node_name IS NOT NULL AND status IN ('Missed') GROUP BY DATE(scheduled_start) -
) as a, -
( -
SELECT DATE(scheduled_start) as "Date", count(*) as -
"Total Client Schedules" FROM events WHERE node_name IS NOT NULL GROUP BY DATE(scheduled_start) -
) as b -
WHERE a."Date" = b."Date" ORDER BY "Date" desc
and Here is the output
Date Missed Total Client Schedules Pct Completed
----------- ------------ ----------------------- --------------
2013-02-20 2 805 100
2013-02-19 14 805 99
2013-02-18 29 805 97
2013-02-17 59 805 93
2013-02-16 29 806 97
2013-02-15 49 805 94
2013-02-14 33 805 96
2013-02-13 57 805 93
2013-02-12 21 805 98
2013-02-11 35 805 96
2013-02-10 34 805 96
it always seems to round to the highest number when i want it to be like 99.99% or 97.2% etc..
You don't specify what database you are using. However, some databases do integer arithmetic, so 1/2 is 0 not 0.5.
To fix this, just make the constants you are using numeric rather than integer:
cast(100.0-((a."Missed"*100.0) / b."Total Client Schedules")AS decimal)
It will then convert to a non-integer type for the arithmetic.