Compare two dates in a snapshot Table -TSQL - sql

I have a snapshot table which has a daily level information for a particular product and its price.
all I want to achieve is compare the state of this product from its current state to its previous state 2 months back.
Here is the ddl
CREATE TABLE Prod_snapshot
('Base_Date' datetime, 'Product_code' varchar(4));
INSERT INTO Prod_snapshot
('Base_Date', 'Product_code')
VALUES
('2013-10-01 13:00:00', 'VD1'),
('2013-10-01 13:00:00', 'VD2'),
('2013-10-01 13:00:00', 'VD2'),
('2013-10-01 13:00:00', 'VD1'),
('2013-10-01 13:00:00', 'VD3'),
('2013-10-01 13:00:00', 'VD9'),
('2014-02-01 13:00:00', 'VD1'),
('2014-02-01 13:00:00', 'VD2'),
('2014-02-01 13:00:00', 'VD10');
Here is the sql fiddle.
Here is my desired Output
Base_date Product_Code Active_on_01_oct_2013
01/02/2014 VD1 'Y'
01/02/2014 VD2 'Y'
01/02/2014 VD10 'N'

The basics of the query would be something like:
DECLARE #DateOfInterest date
SET #DateOfInterest = '20140201'
SELECT p1.Base_Date,pr.Product_Code,
CASE WHEN p2.Product_Code IS NULL THEN 'N' ELSE 'Y' END as PreviouslyActive
FROM
Prod_snapshot p1
left join
Prod_snapshot p2
on
p1.Product_Code = p2.Product_Code and
p2.Base_Date = DATEADD(month,-4 /* narrative says 2 */,#DateOfInterest)
WHERE
p1.Base_Date = #DateOfInterest

Related

LAG function not returning desired results

I have this table:
CREATE TABLE [dbo].[testtable]
(
[EmpID] [int] NOT NULL,
[Status] [nvarchar](5) NOT NULL,
[History] [nvarchar](5) NOT NULL,
[EntryDate] DateTime NOT NULL
)
INSERT INTO [dbo].[testtable] ([EmpID], [Status], [History], EntryDate)
VALUES (1, 'N', 'OLD', '2022-03-01 13:00'),
(1, 'C', 'OLD', '2022-03-01 16:00'),
(1, 'C', 'OLD', '2022-04-01 16:00'),
(1, 'T', 'CUR', '2022-05-01 08:00'),
(2, 'N', 'OLD', '2022-04-01 16:00'),
(2, 'R', 'OLD', '2022-05-01 07:00'),
(2, 'F', 'OLD', '2022-06-01 15:00'),
(2, 'S', 'CUR', '2022-07-01 14:00'),
(3, 'N', 'CUR', '2022-03-01 17:00'),
(4, 'N', 'OLD', '2022-05-01 16:00'),
(4, 'F', 'OLD', '2022-06-01 11:00'),
(4, 'G', 'OLD', '2022-07-01 20:00'),
(4, 'G', 'CUR', '2022-08-01 19:00')
In my current output, it seems the beginning first record of a different ID selects the prior status of the previous EMPID.EMPID3 will not be included since they have no change
SELECT
EMPID, FromSt, ToSt, History
FROM
(SELECT
EMPID,
ISNULL(LAG(Status) OVER (ORDER BY EMPID ASC), 'N') AS FromSt,
 Status AS ToSt,
History
FROM
[dbo].[testable]
-- WHERE History = 'CUR'
) InnerQuery
WHERE
FromSt <> ToSt
Output:
EMPID FromSt ToSt
---------------------
1 N C
1 C T
2 T N
2 N R
2 R F
2 F S
3 S N
4 N F
4 F G
where each EmpID will go through various status changes. The Oldest per EMPID records will always have a Value of STATUS 'N' and OLD in History and the latest record will always have a History value of 'CUR'
Scenario #1
I would like the output to show only when there is a change between records as below when I select all records
EmpID FromSt ToSt
-------------------
1 N C
1 C T
2 N R
2 R F
2 F S
4 N G
Scenario #2
If I only select 'CUR' I want the output to choose the most current status that is different from the current one and where there is a status change. So again EMPID3 would not be included
EmpID FromSt ToSt
-----------------------
1 C T
2 F S
2 R S
4 F G
There are several problems with the code.
In order to evaluate LAG separately for each EMPID, you need to include the PARTITION BY clause in the LAG function.
https://learn.microsoft.com/en-us/sql/t-sql/functions/lag-transact-sql?view=sql-server-ver16
You need to chose what order to sort the data for LAG to use. There doesn't appear to be anything in your data (a date, perhaps) that would enable you to choose the order. Without this, the results won't be consistent as SQL Server doesn't guarantee the the results are returned in any particular order unless you tell it to. Plus LAG requires an ORDER BY clause.
Thanks to dougp advice. here is the solution
SELECT
EMPID,FromSt,ToSt,History
FROM (SELECT EMPID,
ISNULL(LAG(Status) OVER(PARTITION BY Empid ORDER BY EmpID,EntryDate ),'N')As FromSt,  
Status AS ToSt,
History
FROM [dbo].[testtable]
--WHERE History='CUR'
) InnerQuery
WHERE FromSt<>ToSt

Using DimCalendar update days between two dates

In DWH (SQL Server) i have two tables:
DWH.Days
DayStart
DayStop
DaysBetween
2022-04-21
2022-04-24
null
2022-03-12
2022-04-27
null
2022-04-21
2022-04-24
null
2022-03-01
2022-04-22
null
and
DWH.Calendar
Date
IsHoliday?
2022-05-11
yes
2022-05-12
no
2022-05-13
yes
2022-05-15
no
I need to update DWH.Days.DaysBetween as a number of days between DayStart and DayStop where DWH.DimCalendar.IsHoliday?='no'. I don't have premission change the data model. I don't have any ideas how to do it, any ideas?
your data
however there exist numerous issues regarding your sample data
declare #Days table (
DayStart DATE NOT NULL,
DayStop DATE NOT NULL,
DaysBetween VARCHAR(40)
);
INSERT INTO #Days (DayStart, DayStop, DaysBetween)
VALUES
('2022-04-21', '2022-04-24', NULL),
('2022-03-12', '2022-04-27', NULL),
('2022-04-21', '2022-04-24', NULL),
--repeated data it should be deleted
('2022-03-01', '2022-04-22', NULL);
declare #Calendar table(
Date DATE NOT NULL,
IsHoliday VARCHAR(30) NOT NULL
);
INSERT INTO #Calendar (Date, IsHoliday)
VALUES
('2022-05-11', 'yes'),
--actual values
('2022-05-12', 'no'),
--actual values
('2022-05-13', 'yes'),
--actual values
('2022-05-15', 'no'),
--actual values
('2022-04-23', 'yes'),
--added values for test. it can be deleted.
('2022-03-10', 'no'),
--added values for test. it can be deleted.
('2022-03-14', 'yes'),
--added values for test. it can be deleted.
('2022-04-22', 'no'),
--added values for test. it can be deleted.
('2022-03-15', 'no');
first you should use cross join for satisfy the Condition DayStart<Date<DayStop and IsHoliday='no'. then use subquery and DATEDIFF and group by as follows
SELECT Daystart,
Daystop,
Datediff(d, Daystart, Daystop) - Count(Isholiday) AS DaysBetween
FROM (SELECT Daystart,
Daystop,
Daysbetween,
Isholiday
FROM #days d,
#Calendar c
WHERE d.Daystart < c.Date
AND d.Daystop > c.Date
AND c.Isholiday = 'no') a
GROUP BY Daystart,
Daystop

If query returns one or more rows, return the row/rows and exit

I have three statements. If any of them returns anything I want that to be returned and the query to exit.
select *
from connexion
where origin = 'Stockholm'
and destination = 'Berlin';
-- IF IT RETURNS ONE OR MORE ROWS THEN RETURN ROW/ROWS AND EXIT, ELSE GO TO STATEMENT BELOW
select *
from connexion c1, connexion c2
where c1.origin = 'Stockholm'
and c2.destination = 'Berlin'
and c1.destination = c2.origin;
-- IF IT RETURNS ONE OR MORE ROWS THEN RETURN ROW/ROWS AND EXIT, ELSE GO TO STATEMENT BELOW
select *
from connexion c1, connexion c2, connexion c3
where c1.origin = 'Stockholm'
and c3.destination = 'Berlin'
and c1.destination = c2.origin
and c2.destination = c3.origin;
-- IF IT RETURNS ONE OR MORE ROWS THEN RETURN ROW/ROWS AND EXIT, ELSE EXIT
Here's the query to create the database. I want to retrieve a result where I can go from Stockholm to Berlin via any of the available connexions.
create table busstop(
city varchar(50),
country varchar(50) not null,
streetAddress varchar(50) not null,
primary key (city)
);
create table driver(
driverPnr varchar(13),
name varchar(50) not null,
address varchar(50) not null,
phone varchar(12) not null,
primary key (driverPnr)
);
create table customer(
customerPnr varchar(13),
name varchar(50) not null,
email varchar(50) not null,
phone varchar(12) not null,
primary key (customerPnr)
);
create table connexion(
connexionId serial not null,
origin varchar(50) not null,
destination varchar(50) not null,
primary key (connexionId),
foreign key (origin) references busstop(city),
foreign key (destination) references busstop(city)
);
create table trip(
tripId serial not null,
connexionId integer not null,
departure timestamp not null,
arrival timestamp not null,
driverPnr varchar(13),
priceAmount integer not null,
seats integer not null,
primary key (tripId),
foreign key (connexionId) references connexion(connexionId),
foreign key (driverPnr) references driver(driverPnr)
);
create table booking(
customerPnr varchar(13) not null,
tripId integer not null,
seats integer not null,
primary key (customerPnr, tripId),
foreign key (customerPnr) references customer(customerPnr),
foreign key (tripId) references trip(tripId)
);
insert into busstop(city, country, streetAddress) values
('Stockholm', 'Sweden', 'Byvägen 1'),
('Copenhagen', 'Denmark', 'Vesterbrogade 23'),
('Berlin', 'Germany', 'Europaplatz 4'),
('Amsterdam', 'Netherlands', 'Stationsplein 17'),
('Prague', 'Czech Republic', 'Wilsonova 10');
insert into connexion(origin, destination) values
('Stockholm', 'Copenhagen'),
('Copenhagen', 'Stockholm'),
('Copenhagen', 'Berlin'),
('Berlin', 'Copenhagen'),
('Copenhagen', 'Amsterdam'),
('Amsterdam', 'Copenhagen'),
('Berlin', 'Prague'),
('Prague', 'Berlin'),
('Amsterdam', 'Berlin'),
('Berlin', 'Amsterdam'),
('Amsterdam', 'Prague'),
('Prague', 'Amsterdam');
insert into trip(connexionId, departure, arrival, priceAmount, seats) values
-- Exits on 2018-04-21
-- Stockholm - Copenhagen / Copenhagen - Stockholm, 3 hours
(1, '2018-04-22 07:00:00', '2018-04-22 10:00:00', 200, 35),
(2, '2018-04-22 18:00:00', '2018-04-22 21:00:00', 200, 35),
-- Copenhagen - Berlin / Berlin - Copenhagen, 7 hours
(3, '2018-04-22 10:00:00', '2018-04-22 17:00:00', 500, 35),
(4, '2018-04-22 11:00:00', '2018-04-22 18:00:00', 500, 35),
-- Copenhagen - Amsterdam / Amsterdam - Copenhagen, 9 hours
(5, '2018-04-22 10:00:00', '2018-04-22 19:00:00', 800, 35),
(6, '2018-04-22 09:00:00', '2018-04-22 18:00:00', 800, 35),
-- Berlin - Prague / Prague - Berlin, 4 hours
(7, '2018-04-22 17:00:00', '2018-04-22 21:00:00', 300, 35),
(8, '2018-04-22 07:00:00', '2018-04-22 11:00:00', 300, 35),
-- Amsterdam - Berlin / Berlin - Amsterdam, 7 hours
(9, '2018-04-22 07:00:00', '2018-04-22 14:00:00', 500, 35),
(10, '2018-04-22 14:00:00', '2018-04-22 21:00:00', 500, 35),
-- Amsterdam - Prague / Prague - Amsterdam, 9 hours
(11, '2018-04-22 05:00:00', '2018-04-22 14:00:00', 800, 35),
(12, '2018-04-22 14:00:00', '2018-04-22 23:00:00', 800, 35);
If I go from Stockholm to Berlin the query has to first check if there are any direct connexions between Stockholm and Berlin. If no, then it has to check if there are any connexion with ONE stopover, if so retrieve a row for that. If there's none, proceed with checking if there's any connexion with TWO stopovers, and it continues until it has checked THREE stopovers. (no one would want to travel from Stockholm to Berlin with more than three stopovers..).. It's so hard to explain what I want to achieve but I hope you get the point :)
You can do this with multiple joins:
select c1.*, c2.*, c3.*
from connexion c1 left join
connexion c2
on c1.origin = 'Stockholm' and
(c1.destination = 'Berlin' or
(c1.destination <> 'Berlin' and c2.destination = 'Berlin')
) left join
connection c3
on c2.destination = c3.destination and
(c2.destination <> 'Berlin' and
c1.destination <> 'Berlin'
);
a reach and this is tsql
this is just direct or 1 stop
select 'Stockholm' as origin_, 'Berlin' as destination_, *
from connexion c1
join connexion c2
on c1.origin = 'Stockholm'
and ( c1.destination = 'Berlin'
or (c1.destination <> 'Berlin' and c2.destination = 'Berlin')
)
This is sql server but according to the docs postgresql supports recursion.
Stop is just the last stop. This does not show you all stops. Cnt is the number of stops.
declare #t table (orig varchar(20), dest varchar(20)
, primary key (orig, dest));
insert into #t values
('Stockholm', 'Copenhagen'),
('Copenhagen', 'Stockholm'),
('Copenhagen', 'Berlin'),
('Berlin', 'Copenhagen'),
('Copenhagen', 'Amsterdam'),
('Amsterdam', 'Copenhagen'),
('Berlin', 'Prague'),
('Prague', 'Berlin'),
('Amsterdam', 'Berlin'),
('Berlin', 'Amsterdam'),
('Amsterdam', 'Prague'),
('Prague', 'Amsterdam');
with cte as
( select t.orig, t.orig as 'stop', t.dest, 1 as cnt
from #t t
union all
select cte.orig, t.orig, t.dest, cnt + 1
from #t t
join cte
on cte.dest = t.orig
and t.dest <> cte.orig --don't loop back home
and cnt < 4
)
select *
from cte
where orig = 'Stockholm'
and dest = 'Berlin'
order by cnt, cte.stop
This will not prevent looping in route. By limiting cnt the loops are eliminated. It prevents going back to the original city.
You can use GOTo Statement in SQL . In below code you can assign your query counts and then in if condition you can count if its grater than 0 then GOTO respective query.
DECLARE #a Int
DECLARE #b Int
SELECT #a = 10
SELECT #b = 5
BEGIN
IF #a>#0 GOTO Greater
IF #b>0 GOTO Lesser
END
Greater: SELECT #a
Lesser: SELECT #b

Calculating Variance from different data Sources Oracle SQL

I am attempting to create a list of variances based on data that I get from two difference sources. This data contains a date, a series of references and columns containing numeric counts etc.
The idea behind this is to check that the data from Data Source 1 has the same numeric count as the data from Data Source 2, and then logging the variances of each 5 minute interval.
Here I have the required code to create the table and sample data of a simplified scenario
Create Table ABP_PROFILE
( ABP_DATE Date not Null,
ABP_SOURCE_UID Number(10) not Null,
ABP_REFERENCE_1 Varchar2(30) not Null,
ABP_CHARGE Number(18,6),
ABP_COUNT Number(18)
);
insert into ABP_PROFILE (ABP_DATE, ABP_SOURCE_UID, ABP_REFERENCE_1, ABP_CHARGE, ABP_COUNT)
values (to_date('15-06-2015 00:05:00', 'dd-mm-yyyy hh24:mi:ss'), 1, 'Another Reference', 757.500000, 101);
insert into ABP_PROFILE (ABP_DATE, ABP_SOURCE_UID, ABP_REFERENCE_1, ABP_CHARGE, ABP_COUNT)
values (to_date('15-06-2015 00:05:00', 'dd-mm-yyyy hh24:mi:ss'), 1, 'Some Reference', 2954.000000, 211);
insert into ABP_PROFILE (ABP_DATE, ABP_SOURCE_UID, ABP_REFERENCE_1, ABP_CHARGE, ABP_COUNT)
values (to_date('15-06-2015 00:05:00', 'dd-mm-yyyy hh24:mi:ss'), 2, 'Another Reference', 757.500000, 101);
insert into ABP_PROFILE (ABP_DATE, ABP_SOURCE_UID, ABP_REFERENCE_1, ABP_CHARGE, ABP_COUNT)
values (to_date('15-06-2015 00:05:00', 'dd-mm-yyyy hh24:mi:ss'), 2, 'Some Reference', 2954.000000, 211);
insert into ABP_PROFILE (ABP_DATE, ABP_SOURCE_UID, ABP_REFERENCE_1, ABP_CHARGE, ABP_COUNT)
values (to_date('15-06-2015 00:10:00', 'dd-mm-yyyy hh24:mi:ss'), 1, 'Another Reference', 5300.250000, 191);
insert into ABP_PROFILE (ABP_DATE, ABP_SOURCE_UID, ABP_REFERENCE_1, ABP_CHARGE, ABP_COUNT)
values (to_date('15-06-2015 00:10:00', 'dd-mm-yyyy hh24:mi:ss'), 1, 'Some Reference', 9568.000000, 208);
insert into ABP_PROFILE (ABP_DATE, ABP_SOURCE_UID, ABP_REFERENCE_1, ABP_CHARGE, ABP_COUNT)
values (to_date('15-06-2015 00:10:00', 'dd-mm-yyyy hh24:mi:ss'), 2, 'Another Reference', 5300.250000, 5555);
insert into ABP_PROFILE (ABP_DATE, ABP_SOURCE_UID, ABP_REFERENCE_1, ABP_CHARGE, ABP_COUNT)
values (to_date('15-06-2015 00:10:00', 'dd-mm-yyyy hh24:mi:ss'), 2, 'Some Reference', 1111.000000, 208);
Here I have created a BASIC SQL query to how what it is I want to do.
With A_DATA As (
Select ABP_DATE As A_DATE,
ABP_REFERENCE_1 As A_REFERENCE_1,
ABP_CHARGE As A_CHARGE,
ABP_COUNT As A_COUNT
From ABP_PROFILE
Where ABP_SOURCE_UID = 1
), B_DATA As (
Select ABP_DATE As B_DATE,
ABP_REFERENCE_1 As B_REFERENCE_1,
ABP_CHARGE As B_CHARGE,
ABP_COUNT As B_COUNT
From ABP_PROFILE
Where ABP_SOURCE_UID = 2
)
Select A_DATE,
A_REFERENCE_1,
B_CHARGE - A_CHARGE As ChargeDifference,
B_COUNT - A_COUNT As CountDifference
From A_DATA,
B_DATA
Where A_DATE = B_DATE
And A_REFERENCE_1 = B_REFERENCE_1
;
This does a join based on the Date and Reference from the two data sources. I need to have a much more versatile solution which needs to also show variances if data from one side is missing, yes a full outer join can be used for this, but I want to explore other options.
I've been looking into Analytic Functions and I am sure there is one out there which can do what I want it to do. I'm wondering if any Oracle SQL Experts have any ideas that can help here.
FYI I am running 11gR2 Enterprise
Solution with FULL JOIN seems to be more readable, but if you search for alternative - here it is - with functions lag() and lead():
with data as (
select abp_date dt, abp_source_uid id, abp_reference_1 ref,
abp_charge charge, abp_count cnt,
lag(abp_source_uid) over (partition by abp_date, abp_reference_1
order by abp_source_uid) lgid,
lead(abp_charge) over (partition by abp_date, abp_reference_1
order by abp_source_uid) ldcharge,
lead( abp_count) over (partition by abp_date, abp_reference_1
order by abp_source_uid) ldcnt
from abp_profile a)
select dt, ref,
case when id = 1 then nvl(ldcharge, 0) - charge else charge end chrg_diff,
case when id = 1 then nvl(ldcnt, 0) - cnt else cnt end cnt_diff
from data
where id = 1 or id = 2 and lgid is null;
... and your modified query transformed to full join version, which I made to compare results:
With A_DATA As (
Select ABP_DATE As A_DATE,
ABP_REFERENCE_1 As A_REFERENCE_1,
ABP_CHARGE As A_CHARGE,
ABP_COUNT As A_COUNT
From ABP_PROFILE
Where ABP_SOURCE_UID = 1
), B_DATA As (
Select ABP_DATE As B_DATE,
ABP_REFERENCE_1 As B_REFERENCE_1,
ABP_CHARGE As B_CHARGE,
ABP_COUNT As B_COUNT
From ABP_PROFILE
Where ABP_SOURCE_UID = 2
)
Select nvl(A_DATE, b_date) dt,
nvl(A_REFERENCE_1, b_reference_1) ref,
nvl(B_CHARGE, 0) - nvl(A_CHARGE, 0) As Chrg_Diff,
nvl(B_COUNT, 0) - nvl(A_COUNT, 0) As Cnt_Diff
From A_DATA
full join B_DATA on A_DATE = B_DATE and A_REFERENCE_1 = B_REFERENCE_1;
SQLFiddle
Both queries qives same results. In examples I added two rows to show how to deal with missing data.
Here I used nvl(..., 0) but of course you can leave nulls or add column(s) informing of such situation.

RANKING for counting phone numbers

Thanks for all your suggestions.It works fine on a small test data but I guess I under-estimated the total rows and plans so I guess I will have to post some biggers sample data
Here it is:
CREATE TABLE MasterTable
(`Date` datetime, `PhNO` int, `Plan_name` varchar(13), `Plan_price` varchar(3))
;
INSERT INTO MasterTable
(`Date`, `PhNO`, `Plan_name`, `Plan_price`)
VALUES
('2014-01-01 13:00:00', 3232222, 'Basepack1', '$32'),
('2014-01-01 13:00:00', 3232222, 'Basepack2', '$31'),
('2014-01-01 13:00:00', 3221111, 'Basepack6', '$21'),
('2014-01-01 13:00:00', 543222, 'BaseValuePack', '$76'),
('2014-01-01 13:00:00', 543222, 'Basepack1', '$30'),
('2014-01-01 13:00:00', 32322221, 'Basepack1', '$37'),
('2014-01-01 13:00:00', 32322221, 'Basepack2', '$21'),
('2014-01-01 13:00:00', 32322354, 'Basepack7', '$23'),
('2014-01-01 13:00:00', 32322254, 'Basepack8', '$11'),
('2014-01-01 13:00:00', 3267767, 'Non-base1', '$21'),
('2014-01-01 13:00:00', 3267762, 'Non-base1', '$21'),
('2014-01-01 13:00:00', 32677676, 'Non-base3', '$76'),
('2014-01-01 13:00:00', 5267767, 'Non-base9', '$21')
Now I basically want to group all the 'Non-base%' plans under 'Casual' category
Here is the desired output:
Date Plan_name Phone_no_count
'2014-01-01 13:00:00' 'Basepack1' 2
'2014-01-01 13:00:00' 'Basepack2' 0
'2014-01-01 13:00:00' 'Basepack6' 1
'2014-01-01 13:00:00' 'BaseValuepack' 1
'2014-01-01 13:00:00' 'Casual' 4
Thanks
...........................................
Previous request:
I need to count all the phone nos categorised by certain plans. But to group those plans, I need to rank them first based on their price.
Here is the ddl
CREATE TABLE MasterTable
(`Date` datetime, `PhNO` int, `Plan_name` varchar(13), `Plan_price` varchar(3))
;
INSERT INTO MasterTable
(`Date`, `PhNO`, `Plan_name`, `Plan_price`)
VALUES
('2014-01-01 13:00:00', 3232222, 'Basepack1', '$32'),
('2014-01-01 13:00:00', 3232222, 'Basepack2', '$31'),
('2014-01-01 13:00:00', 3221111, 'Basepack6', '$21'),
('2014-01-01 13:00:00', 543222, 'BaseValuePack', '$76'),
('2014-01-01 13:00:00', 543222, 'Basepack1', '$30'),
('2014-01-01 13:00:00', 32322221, 'Basepack1', '$37'),
('2014-01-01 13:00:00', 32322221, 'Basepack2', '$21')
;
Now the rule is, I only need to count a phone no once who has more than 1 plan based on their plan price(higher one) .
But there is also a scenario where a phone no has two different 'packs'- Basepack and valuepack, which means I need to count that phone no only once categorised under value pack(in this case we need to ignore the price).
Here is the desired output.
Date Plan_name Phone_no_count
-------------------------------------------------
'2014-01-01 13:00:00' 'Basepack1' 2
'2014-01-01 13:00:00' 'Basepack2' 0
'2014-01-01 13:00:00' 'Basepack6' 1
'2014-01-01 13:00:00' 'BaseValuepack' 1
How do I use the rank function to achieve this result?
Try this code, Assuming it is mysql as the code posted looks like mysql
SELECT date,
plan_name,
Sum((SELECT Count(1)
FROM mastertable T2
WHERE t2.phno = tt.phno
AND t2.date = Tt.date
AND ( tt.plan_price > t2.plan_price
OR TT.count = 1 ))) CNT
FROM (SELECT *,
(SELECT Count(1)
FROM mastertable Ti
WHERE ti.date = T.date
AND ti.phno = t.phno) AS Count
FROM mastertable T) Tt
GROUP BY date,
plan_name
Here is the SQL Fiddle Demo
;with cte as
(
select *,ROW_NUMBER()over(partition by phno order by plan_price desc)rn
from #MasterTable
)
,
cte1 as
(
select a.Plan_name,count(*)[Phone_no_count] from cte a
where rn=1
group by a.Plan_name
)
select distinct a.dates,a.Plan_name,isnull(b.Phone_no_count,0)[[Phone_no_count]
from #MasterTable a left join cte1 b on a.Plan_name=b.Plan_name