How can i implement this query in sql server? - sql-server

I'm beginner in sql server,have two table ,table GetOnlineBills with this shape:
--Telno-- --Cycle-- --Bill--
nchar(20) nchar(20) float
And table 25Percantage:
--Telno-- --Cycle-- --Bill--
nchar(20) nchar(20) float
want to write query or tsql for analysis Telno in GetOnlineBill table with this flow:
1-fetch Telno ang get it bill value in Cycle 951 and Cycle 952
2-If Bill(952)>Bill(951) then write into 25 percantage this data (Bill(952)-Bill(951))
into GetOnlineBill's table write subscribe Bill information per cycle,For example have two subscribe(in really world have 1 million subscribe) with this plan:
into the GetOnlineBills one mounth data is this:
--Telno-- --Cycle-- --Bill--
12345 951 300
54321 951 500
and other month data is :
--Telno-- --Cycle-- --Bill--
12345 952 400
54321 952 600
and final GetOnlineBill for two mounth is:
--Telno-- --Cycle-- --Bill--
12345 951 300
54321 951 500
12345 952 400
54321 952 600
Now,i want analysis GetOnlineBill,want write query or tsql to create final 25Percantage table show me this:
--Telno-- --Cycle-- --Bill--
12345 951-952 100 ------>Bill(952)-Bill(951) Minus
54321 951-952 300
----------------------------------------
Explain:
Bill:Field Name on GetOnlineBill table
952:Cycle
951:Cycle
How can i write query or tsql for that purpose?please write and post me.thanks all.

Inner join should help you:
SELECT y.Telno,
t.Cycle+'-'+y.Cycle Cycle,
y.Bill - t.Bill Price
FROM YourTable y
INNER JOIN YourTable t
ON y.Telno = t.TelNo AND CAST(y.Cycle as int)-1 = CAST(t.Cycle as int)
Output:
Telno Cycle Price
12345 951-952 100
54321 951-952 100
If Cycle column can not be converted to integer then you need some other field to order table right way and do join with that field (or OUTER APPLY)

Try as the below:
DECLARE #Tbl TABLE (TelNo NCHAR(20), Cycle NCHAR(20), Bill FLOAT)
INSERT INTO #Tbl
VALUES
('12345', '951', 300),
('12345', '952', 400),
('54321', '951', 500),
('54321', '952', 600)
;WITH CTE
AS
(
SELECT *, DENSE_RANK() OVER (ORDER BY Cycle) MonthId
FROM #Tbl
)
SELECT
CurrentMonth.TelNo,
CurrentMonth.Cycle + '-' + NextMonth.Cycle Cycle,
CASE
WHEN NextMonth.Bill > CurrentMonth.Bill THEN NextMonth.Bill - CurrentMonth.Bill
ELSE CurrentMonth.Bill END Bill -- Change as you want
FROM
CTE CurrentMonth LEFT JOIN
CTE NextMonth ON CurrentMonth.TelNo = NextMonth.TelNo AND (NextMonth.MonthId - 1) = CurrentMonth.MonthId
WHERE
NextMonth.MonthId IS NOT NULL
Result:
TelNo Cycle Bill
-------------------- ------------------------ ---------
54321 951-952 100
12345 951-952 100

Related

How can I match a row in SQL Server only once?

I have the following problem where I am kindly asking for your help when joining two tables in SQL Server 2016 (v13).
I have 2 tables, Revenues and Cashins.
Revenues:
RevenueID
ProductID
InvoiceNo
Amount
123
456
987
1000
234
456
987
1000
Cashins:
CashinID
ProductID
InoviceNo
Amount
ABC
456
987
1000
CDE
456
987
1000
The goal is to match cashins automatically to revenues (but only once!).
Both tables have their unique-ids but the columns used to join these tables are
ProductID
InvoiceNo
Amount
For entries with only one row in each table with those criteria, everything works fine.
Sometimes though, there are several rows that have the same value within these columns (as above) but with a unique ID (this is no error, but the way it is supposed to be).
The problem with it is, that while joining it results in a cartesian product.
To recreate the tables, here the statements:
DROP TABLE IF EXISTS Revenues
GO
CREATE TABLE Revenues
(
RevenueID [nvarchar](10) NULL,
ProductID [nvarchar](10) NULL,
InvoiceNo [nvarchar](10) NULL,
Amount money NULL
)
GO
DROP TABLE IF EXISTS CashIns
GO
CREATE TABLE CashIns
(
CashinID [nvarchar](10) NULL,
ProductID [nvarchar](10) NULL,
InvoiceNo [nvarchar](10) NULL,
Amount money NULL
)
GO
INSERT INTO [Revenues] VALUES ('123', '456', '987', 1000)
INSERT INTO [Revenues] VALUES ('234', '456', '987', 1000)
INSERT INTO [CashIns] VALUES ('ABC', '456', '987', 1000)
INSERT INTO [CashIns] VALUES ('BCD', '456', '987', 1000)
Desired output:
RevenueID
ProductID
InvoiceNo
Amount
CashinID
123
456
987
1000
ABC
234
456
987
1000
CDE
SELECT
R.RevenueID,
R.ProductID,
R.InvoiceNo,
R.Amount,
C.CashinID,
FROM
[Revenues] R
LEFT JOIN
[CashIns] C ON R.ProductID = C.ProductID
AND R.InvoiceNo = C.InvoiceNo
AND R.Amount = C.Amount
Results:
RevenueID
ProductID
InvoiceNo
Amount
CashinID
123
456
987
1000
ABC
123
456
987
1000
CDE
234
456
987
1000
ABC
234
456
987
1000
CDE
Which in theory makes sense, but I just can't seem to find a solution where each row is just used once.
Two things I found and tried are windowing functions and the OUTER APPLY function with a TOP(1) selection. Both came to the same result:
SELECT
*
FROM
[Revenues] R
OUTER APPLY
(SELECT TOP(1) *
FROM [CashIns] C) C
Which returns the desired columns from the Revenues table, but only matched the first appearance from the Cashins table:
RevenueID
ProductID
InvoiceNo
Amount
CashinID
123
456
987
1000
ABC
234
456
987
1000
ABC
I also thought about something like updating the Revenues table, so that the matched CashinID is next to a line and then check every time that the CashinID is not yet used within that table, but I couldn't make it work...
Many thanks in advance for any help or hint in the right direction!
As I said in my comment, you have a fundamental problem with your data relationships. You need to reference the unique identifier of the other table in one of your tables. If you don't do that, then you can only order your transactions in both tables and join them by the row number. You're using a hope and prayer to join your data instead of unreputable identifier's.
--This example orders the transactions in each transaction table and uses
--the order number to join them.
WITH RevPrelim AS (
SELECT *
, ROW_NUMBER() OVER(PARTITION BY InvoiceNo, ProductID, Amount ORDER BY RevenueID) AS row_num
FROM [Revenues] R
), CashinsPrelim AS (
SELECT *
, ROW_NUMBER() OVER(PARTITION BY InvoiceNo, ProductID, Amount ORDER BY CashinID) AS row_num
FROM [CashIns] AS C
)
SELECT *
FROM RevPrlim AS r
LEFT OUTER JOIN CashinsPrelim AS c
ON c.ProductID = r.ProductID
AND c.InvoiceNo = r.InvoiceNo
AND c.Amount = r.Amount
AND c.row_num = r.row_num

How To Pivot table using SQL server

i creating SQL table its have three column fields
NAME TYPE Amount
RAJ 401K % 500
Kumar ROTH 600
RAJ 401K % 500
Kumar ROTH 700
Karthi 401K % 1500
RAj Roth 800
Tony DPD 8
above table i have three column Fields Name and Type finally Amount. i try convert this table like separate columns Type. in my table Raj come in table many time so i want to sum Raj all value which values come with 401K table finally its show single value. its added 401k value. Roth value seperate like this
Name 401k% Roth Amount
Raj 1000 800 1800
Kumar 0 1300 1300
Karthi 1500 0 1500.
Nimi 0 0 0 -- this is should Remove only value come with only 401k% and Roth . other value should be delete .
i want like this. i am trying to achive this using Pivot talbe i am getting Null value
select [Name],[401k%] ,[Roth%]
from DeductionHistory
PIVOT
( SUM(Amount) FOR DeductionName IN([401k%],[Roth%])
)
AS Pivottable
please any one help me . how to get value Like this
CREATE TABLE #TABLE111
([NAME] VARCHAR(6), [TYPE] VARCHAR(6), [AMOUNT] INT)
INSERT INTO #TABLE111
([NAME], [TYPE], [AMOUNT])
VALUES
('RAJ', '401K %', 500),
('KUMAR', 'ROTH', 600),
('RAJ', '401K %', 500),
('KUMAR', 'ROTH', 700),
('KARTHI', '401K %', 1500),
('RAJ', 'ROTH', 800)
SELECT NAME ,ISNULL([401K %],0) [401K %] ,ISNULL([ROTH],0) [ROTH] ,ISNULL([401K %],0)+ISNULL([ROTH],0) 'TOTAL'
FROM
(
SELECT *
FROM #TABLE111
) SRC
PIVOT
(
SUM([AMOUNT])
FOR [TYPE] IN ([401K %], [ROTH] )
) PIV
ORDER BY NAME DESC
output
NAME 401K % ROTH TOTAL
RAJ 1000 800 1800
Kumar 0 1300 1300
Karthi 1500 0 1500
--I have included DPD the query
DECLARE #DeductionHistory TABLE (NAME VARCHAR(20), [TYPE] VARCHAR(20),Amount MONEY)
INSERT INTO #DeductionHistory VALUES
('RAJ','401K%',500),
('Kumar','ROTH',600),
('RAJ','401K%',500),
('Kumar','ROTH',700),
('Karthi','401K%',1500),
('RAj','ROTH',800),
('Tony' ,'DPD', 8)
/*****Use a VTE or temp table*****/
;WITH DeductionHistory
AS(
SELECT * FROM #DeductionHistory
PIVOT
(
SUM(Amount) FOR [TYPE] IN ([401K%],[ROTH],[DPD])
) PV1
)
SELECT
[NAME]
,ISNULL([401K%],0) AS [401K%]
,ISNULL([ROTH],0) AS [ROTH]
,ISNULL([DPD],0) AS [DPD]
,ISNULL([401K%],0)+ISNULL([ROTH],0)+ISNULL([DPD],0) AS Amount
FROM DeductionHistory
OUTPUT
NAME 401K% ROTH DPD Amount
Karthi 1500.00 0.00 0.00 1500.00
Kumar 0.00 1300.00 0.00 1300.00
RAJ 1000.00 800.00 0.00 1800.00
Tony 0.00 0.00 8.00 8.00

How can i write query to calc percent of the difference two field?

I'm new in sql server,have this table on sql server:
Telno nchar(20)
CurBill float
Cycle nchar(8)
and into that table has this data:
Telno CurBill Cycle
123 2000 951
123 2500 952
write this query for calculate difference two number:
SELECT y.Telno,
t.Cycle+'-'+y.Cycle Cycle,
y.CurBill - t.CurBill Price
FROM [ClubEatc].[dbo].[GetOnlineBills] y
INNER JOIN [ClubEatc].[dbo].[GetOnlineBills] t
ON y.Telno = t.TelNo AND CAST(y.Cycle as int)-1 = CAST(t.Cycle as int)
that query minus two CurBill per Cycle and show me this:
123 951-952 1000 ----->calc this formull(CurBill(952)-CurBill(951))
now want to show percent of decrease or increase of CurBill minus,for example show me this:
123 951-952 150%--->calc formulla(CurBill(951)-CurBill(952))/CurBill(951) *100
and other example imagine GetOnlineBills data is this:
Telno CurBill Cycle
123 2500 951
123 2000 952
and show me this:
123 951-952 -150%--->calc formulla(CurBill(951)-CurBill(952))/CurBill(951) *100
How can i implant that?thanks.

Finding the difference within a SQL Server query and dividing by seconds elapsed between records

Hi I have a table of meter values in a SQL Server database, which contains a table with the following columns:
Timestamp, meterID, rawValue
I am trying to graph the water usage rate using a query and google charts, the problem is that I need to calculate the rate from the raw meter values which are updated every 15 to 30 minutes.
I want to run a query that returns the values for a specific water meter.
MeterID, Timestamp, (rawValue-previousRawValue)/(timestamp difference in seconds)
any help is much appreciated.
Edit 1: I have modified index definition to eliminate LookUp operator => fewer logical reads.
Edit 2: I have added the second solution based on quirky update method. Please read this article (Solving the Running Total and Ordinal Rank Problems) written by Jeff Moden.
First solution can be tested with SQL Server 2005/2008:
--Create test table
CREATE TABLE dbo.MeterValues
(
ID INT IDENTITY(1,1) PRIMARY KEY
,[Timestamp] DATETIME NOT NULL
,MeterID INT NOT NULL
,RawValue INT NOT NULL
);
CREATE UNIQUE INDEX IUN_MeterValues_MeterID_Timestamp
--SQL Server 2008
ON dbo.MeterValues (MeterID, [Timestamp])
INCLUDE (RawValue)
--SQL Server 2005
--ON dbo.MeterValues (MeterID, [Timestamp],RawValue)
--DROP INDEX dbo.MeterValues.IUN_MeterValues_MeterID_Timestamp
--Insert some values
INSERT dbo.MeterValues ([Timestamp], MeterID, RawValue)
SELECT '2011-01-01T00:00:00', 1, 100
UNION ALL
SELECT '2011-01-01T00:00:15', 1, 105
UNION ALL
SELECT '2011-01-01T00:00:30', 1, 102
UNION ALL
SELECT '2011-01-01T00:00:45', 1, 108
UNION ALL
SELECT '2011-01-01T00:01:00', 1, 109
UNION ALL
SELECT '2011-01-01T00:00:00', 2, 1000
UNION ALL
SELECT '2011-01-01T00:00:15', 2, 900
UNION ALL
SELECT '2011-01-01T00:00:30', 2, 1105
UNION ALL
SELECT '2011-01-01T00:00:45', 2, 1050
UNION ALL
SELECT '2011-01-01T00:01:00', 2, 910;
--Check test data
SELECT *
FROM dbo.MeterValues mv
ORDER BY mv.MeterID, mv.ID DESC;
--Solution
WITH ValuesWithRowNumber
AS
(
SELECT mv.MeterID
,mv.RawValue
,mv.[Timestamp]
,ROW_NUMBER() OVER(PARTITION BY mv.MeterID ORDER BY mv.[Timestamp] ASC) RowNum
FROM dbo.MeterValues mv
)
SELECT crt.MeterID
,crt.[Timestamp] AS CrtTimestamp
,prev.[Timestamp] AS PrevTimestamp
,crt.RawValue AS CrtRawValue
,prev.RawValue AS PrevRawValue
,(crt.RawValue - prev.RawValue)*1.00/DATEDIFF(SECOND, prev.[Timestamp], crt.[Timestamp]) Diff
,STR((crt.RawValue - prev.RawValue)*1.00/DATEDIFF(SECOND, prev.[Timestamp], crt.[Timestamp])*100, 10, 2)+'%' [Percent]
FROM ValuesWithRowNumber crt --crt=current
LEFT JOIN ValuesWithRowNumber prev ON crt.MeterID = prev.MeterID --prev=previous
AND crt.RowNum - 1 = prev.RowNum
ORDER BY crt.MeterID, crt.[Timestamp] DESC;
--By, by
DROP TABLE dbo.MeterValues;
Results:
MeterID CrtTimestamp PrevTimestamp CrtRawValue PrevRawValue Diff Percent
----------- ----------------------- ----------------------- ----------- ------------ --------------------------------------- -----------
1 2011-01-01 00:01:00.000 2011-01-01 00:00:45.000 109 108 0.0666666666666 6.67%
1 2011-01-01 00:00:45.000 2011-01-01 00:00:30.000 108 102 0.4000000000000 40.00%
1 2011-01-01 00:00:30.000 2011-01-01 00:00:15.000 102 105 -0.2000000000000 -20.00%
1 2011-01-01 00:00:15.000 2011-01-01 00:00:00.000 105 100 0.3333333333333 33.33%
1 2011-01-01 00:00:00.000 NULL 100 NULL NULL NULL
2 2011-01-01 00:01:00.000 2011-01-01 00:00:45.000 910 1050 -9.3333333333333 -933.33%
2 2011-01-01 00:00:45.000 2011-01-01 00:00:30.000 1050 1105 -3.6666666666666 -366.67%
2 2011-01-01 00:00:30.000 2011-01-01 00:00:15.000 1105 900 13.6666666666666 1366.67%
2 2011-01-01 00:00:15.000 2011-01-01 00:00:00.000 900 1000 -6.6666666666666 -666.67%
2 2011-01-01 00:00:00.000 NULL 1000 NULL NULL NULL
The second solution can/should work with SQL 2000/2005/2008 (please read "The RULES" section from Jeff Moden article):
--Create test table
CREATE TABLE dbo.MeterValues
(
MeterID INT NOT NULL
,[Timestamp] DATETIME NOT NULL
,RawValue INT NOT NULL
,Diff NUMERIC(10,3) NULL
,PRIMARY KEY CLUSTERED(MeterID,[Timestamp])
);
--Insert some values
INSERT dbo.MeterValues ([Timestamp], MeterID, RawValue)
SELECT '2011-01-01T00:00:00', 1, 100
UNION ALL
SELECT '2011-01-01T00:00:15', 1, 105
UNION ALL
SELECT '2011-01-01T00:00:30', 1, 102
UNION ALL
SELECT '2011-01-01T00:00:45', 1, 108
UNION ALL
SELECT '2011-01-01T00:01:00', 1, 109
UNION ALL
SELECT '2011-01-01T00:00:00', 2, 1000
UNION ALL
SELECT '2011-01-01T00:00:15', 2, 900
UNION ALL
SELECT '2011-01-01T00:00:30', 2, 1105
UNION ALL
SELECT '2011-01-01T00:00:45', 2, 1050
UNION ALL
SELECT '2011-01-01T00:01:00', 2, 910;
--Check test data
SELECT *
FROM dbo.MeterValues mv
ORDER BY mv.MeterID, mv.[Timestamp];
DECLARE #OldRawValue INT
,#Diff NUMERIC(10,3)
,#OldMeterID INT
,#OldTimestamp DATETIME;
PRINT '*****Star*****'
--Calculations
UPDATE dbo.MeterValues WITH(TABLOCKX)
SET #Diff = CASE WHEN #OldMeterID = MeterID THEN (RawValue - #OldRawValue)*1.00/DATEDIFF(SECOND,#OldTimeStamp,[TimeStamp]) END
,Diff = #Diff
,#OldRawValue = RawValue
,#OldMeterID = MeterID
,#OldTimestamp = [Timestamp]
OPTION(MAXDOP 1);
--Results
SELECT *
FROM dbo.MeterValues mv
ORDER BY mv.MeterID, mv.[Timestamp];
PRINT '*****Stop*****'
--By, by
DROP TABLE dbo.MeterValues;
Results:
MeterID Timestamp RawValue Diff
----------- ----------------------- ----------- ---------------------------------------
1 2011-01-01 00:01:00.000 109 0.067
1 2011-01-01 00:00:45.000 108 0.400
1 2011-01-01 00:00:30.000 102 -0.200
1 2011-01-01 00:00:15.000 105 0.333
1 2011-01-01 00:00:00.000 100 NULL
2 2011-01-01 00:01:00.000 910 -9.333
2 2011-01-01 00:00:45.000 1050 -3.667
2 2011-01-01 00:00:30.000 1105 13.667
2 2011-01-01 00:00:15.000 900 -6.667
2 2011-01-01 00:00:00.000 1000 NULL
Try this
Select a.metered,a.timestamp,
(a.rawValue-b.rawValue)/(a.timestamp-b.timestamp)
From meters A
Join (selec top 2 rawValue,Timestamp
From meters where metered = #meter
order by timestamp DESC) b
On b.timestamp <> a.timestamp and a.meterId=B.meterId
Added a DESC to the timestamp in the middle query. This will cause the most recent two timestamps to be returned, and then the JOIN will "filter out" the one that matches the current row from A
I made a few minor changes to both my query and #Bogdan's query to make them as similar as possible, then compared them. Bogdan's modified query is at the bottom of this post.
Stacked together in the same query, according to the SQL Server Query Execution Plan, mine is 53% of the query cost, and Bogdan's is 47%.
For the data set offered in the Bogdan's post:
My query: 6 scans and 27 logical reads
Bogdan's: 6 scans and 72 logical reads
I added values every 15secs up to 5mins for both meterID 1 and 2, for a total of 42 records, then reran the queries with SQL Server Profiler.
Where my query wins on reads, Bogdan's still wins on CPU and Duration.
CPU SCANS READS DURATION
--------------------------------------
Mine 47 22 313 249ms
Bogdan's 16 22 972 15ms
--------------------------------------
I'm making a few assumptions, like that your MeterID is an INT. Change that as necessary.
I'm also assuming since you want to run the query for a specific meter ID, that it will be passed in as a parameter to a stored procedure.
This should work on SQL Server 2005 and later.
I do a few things that might distract from the actual solution. The core logic is really within the WHILE loop.
CREATE PROCEDURE [dbo].[GetMeterResults]
#MeterID INT
AS
BEGIN
-- create a temp table to store results
CREATE TABLE #tempResults
(
MeterID INT,
[Timestamp] DATETIME,
Result FLOAT
)
DECLARE
#Timestamp DATETIME,
#RawValue INT,
#LastTimestamp DATETIME,
#LastRawValue INT,
#FirstRun BIT = 1
DECLARE cr CURSOR FAST_FORWARD FOR
SELECT
[Timestamp],
RawValue
FROM
YourTable
WHERE
MeterID = #MeterID
ORDER BY
[Timestamp]
OPEN cr
FETCH NEXT FROM cr INTO #Timestamp, #RawValue
WHILE (##FETCH_STATUS = 0)
BEGIN
IF (#FirstRun = 1)
BEGIN -- the first run
SELECT #FirstRun = 0 -- flip the bit for all future runs
END
ELSE -- all subsequent runs after the first
BEGIN
INSERT INTO
#tempResults
SELECT
#MeterID,
#Timestamp,
(#RawValue - #LastRawValue) * 1.00 / DATEDIFF(s, #LastTimestamp, #Timestamp)
END
-- save the current values for comparison on the next run
SELECT
#LastTimestamp = #Timestamp,
#LastRawValue = #RawValue
FETCH NEXT FROM cr INTO #Timestamp, #RawValue
END
CLOSE CR
DEALLOCATE CR
-- return the result set
SELECT
*
FROM
#tempResults
-- clean up the temp table
DROP TABLE #tempResults
END
GO
Bogdan's modified query that filters by MeterID for an apples-to-apples comparison with my query above:
DECLARE #MeterID INT = 1;
WITH ValuesWithRowNumber
AS
(
SELECT mv.MeterID
,mv.RawValue
,mv.[Timestamp]
,ROW_NUMBER() OVER(PARTITION BY mv.MeterID ORDER BY mv.[Timestamp] ASC) RowNum
FROM dbo.MeterValues mv
WHERE mv.MeterID = #MeterID
)
SELECT crt.MeterID
,crt.[Timestamp] AS CrtTimestamp
,prev.[Timestamp] AS PrevTimestamp
,crt.RawValue AS CrtRawValue
,prev.RawValue AS PrevRawValue
,(crt.RawValue - prev.RawValue)*1.00/DATEDIFF(SECOND, prev.[Timestamp], crt.[Timestamp]) Diff
FROM ValuesWithRowNumber crt --crt=current
JOIN ValuesWithRowNumber prev ON crt.RowNum - 1 = prev.RowNum
ORDER BY crt.[Timestamp];

SQL query for top and bottom value for a particular date

SQL Server 2000
My Table:
CARDNO CARDEVENTDATE CARDEVENTTIME
121 20090610 025050
121 20090611 040000
121 20090611 050000
121 20090611 020000
122 20090611 030001
122 20090611 030000
123 20090611 080000
123 20090611 100000
123 20090611 132449
123 20090611 025959
124 20090610 030000
124 20090612 030001
125 20090611 030002
125 20090612 040000
Cardno is Separate Table
Cardeventdate, cardeventtime is separate table
From the above table I want to get Top Time and Bottom Time for the Particular cardeventdate and Cardno
For the 121, 20090611, Top Time is 040000, Bottom Time is 020000
For 123, 20090611, Top Time is 080000, Bottom Time is 025959 …
Like this I need.
I used Min (time) and Max (time), But it showing like this.
For CardNo – 121
Cardeventdate – 20090611
Min Time – 020000
Max Time – 040000
I don’t want to get min and Max, I need only top and Bottom (or) First and Last time value of the particular Date and Cardno.
I used this Query
SELECT RowNumber = IDENTITY (int, 1, 1), CARDNO, CARDEVENTDATE, CARDEVENTTIME INTO #Table1 FROM T_CARDEVENT SELECT t1.CARDNO, t1.CARDEVENTDATE, t1.CARDEVENTTIME FROM #Table t1 INNER JOIN (SELECT RowNumber = MIN(RowNumber), CARDEVENTDATE, CARDNO FROM #Table1 t WHERE (cardeventdate > 20090601) GROUP BY cardno, cardeventdate UNION ALL SELECT MAX(RowNumber), CARDEVENTDATE, CARDNO FROM #Table1 t WHERE (cardeventdate > 20090601) GROUP BY cardno, cardeventdate) t2 ON t2.rownumber = t1.rownumber
Output:
ROWNUMBER CARDNO CARDEVENTDATE CARDEVENTTIME
335 0121 20090611 040000
1099 0121 20090611 050000
1100 0121 20090611 025050
336 0121 20090612 020000
337 0122 20090611 030001
338 0122 20090612 030000
339 0123 20090611 080000
1101 0123 20090611 100000
1102 0123 20090611 132449
340 0123 20090612 025959
341 0124 20090611 030000
342 0124 20090612 030001
343 0125 20090611 030002
344 0125 20090612 040000
So Here Row Number is created for all columns, from that how I have to take First Time and Last Time for the Particular Date.
Expecting Output
CARDNO CARDEVENTDATE CARDEVENTTIME Expecting
0121 20090611 040000 Top Value
0121 20090611 020000 No Need
0121 20090611 025050 Bottom Value
……… so on
Need Query Help.
Well, unless you have some additional fields to establish an order, this is non deterministic. Given the three values for the 23-04-2009 - how is it that APPLE is the first and ROSE is the last? If the ID and the DATE are the same for all three entries, there's no order defined to filter out "GRAPHE"......
Marc
UPDATE: I expanded on Lieven's idea a bit and got this working in my setup:
DECLARE #TempTable TABLE (RowNumber INT IDENTITY(1,1),
DayNumber INT,
ID VARCHAR(3), DateField DATETIME, Value VARCHAR(32))
INSERT INTO #TempTable(DayNumber, id, datefield, value)
SELECT DATEPART(DAYOFYEAR, DateField), ID, DateField, Value
FROM #Table
SELECT *
FROM #TempTable t
INNER JOIN
(SELECT RowNumber = MIN(RowNumber), DayNumber, ID
FROM #TempTable t
GROUP BY DayNumber, t.ID
UNION ALL
SELECT MAX(RowNumber), DayNumber, ID
FROM #TempTable t
GROUP BY DayNumber, t.ID) t2
ON t2.RowNumber = t.RowNumber
GO
I'm basically creating a temp table with additional info - an artificial "RowNumber" to create some order, and the "DayNumber" to get dates grouped by date only (without time).
Seems to work ok for me - does it work for you, too?
Jash, if you execute this script, does it give you the results you'd expect?
CREATE TABLE #T_Cardevent (CARDNO VARCHAR(3), CARDEVENTDATE VARCHAR(8), CARDEVENTTIME VARCHAR(8))
INSERT INTO #T_Cardevent VALUES ('121', '20090610', '025050')
INSERT INTO #T_Cardevent VALUES ('121', '20090611', '040000')
INSERT INTO #T_Cardevent VALUES ('121', '20090611', '050000')
INSERT INTO #T_Cardevent VALUES ('121', '20090611', '020000')
INSERT INTO #T_Cardevent VALUES ('122', '20090611', '030001')
INSERT INTO #T_Cardevent VALUES ('122', '20090611', '030000')
INSERT INTO #T_Cardevent VALUES ('123', '20090611', '080000')
INSERT INTO #T_Cardevent VALUES ('123', '20090611', '100000')
INSERT INTO #T_Cardevent VALUES ('123', '20090611', '132449')
INSERT INTO #T_Cardevent VALUES ('123', '20090611', '025959')
INSERT INTO #T_Cardevent VALUES ('124', '20090610', '030000')
INSERT INTO #T_Cardevent VALUES ('124', '20090612', '030001')
INSERT INTO #T_Cardevent VALUES ('125', '20090611', '030002')
INSERT INTO #T_Cardevent VALUES ('125', '20090612', '040000')
SELECT
RowNumber = IDENTITY (int, 1, 1)
, CARDNO
, CARDEVENTDATE
, CARDEVENTTIME
INTO #Table
FROM #T_CARDEVENT
SELECT t1.CARDNO, t1.CARDEVENTDATE, t1.CARDEVENTTIME
FROM #Table t1
INNER JOIN (
SELECT RowNumber = MIN(RowNumber), CARDEVENTDATE, CARDNO
FROM #Table t
GROUP BY cardno, cardeventdate
UNION ALL SELECT MAX(RowNumber), CARDEVENTDATE, CARDNO
FROM #Table t
GROUP BY cardno, cardeventdate) t2 ON t2.rownumber = t1.rownumber
ORDER BY 1, 2, 3
DROP TABLE #Table
DROP TABLE #T_Cardevent
I havn't tried it, but maybe something like this might do it:
SELECT TOP(1) FROM Table
WHERE Date='Some-date'
AND Id=Some-Id
ORDER BY Date ASC
UNION
SELECT TOP(1) FROM Table
WHERE Date='Some-date'
AND Id=Some-Id
ORDER BY Date Desc
to cheat you can add an autonumber feild
AUtoID ID DATE VALUE
1 001 23:04:2009 APPLE
2 001 23:04:2009 GRAPHE
3 001 23:04:2009 ROSE
4 001 24:04:2009 BERRY
5 001 24:04:2009 TIFFANY
6 001 24:04:2009 ORGANE
7 001 24:04:2009 SILVER
You can then do min and max against it
I usually use insert into a tempory table which is defined with the ID, technically the insertion order isn't garenteed going in.
Here's the solution using inline views:
with
tempFirst as (
select id, date, value,
row_number() over (partition by id, date order by date asc) as rownum1
from table1
),
tempLast as (
select *,
row_number() over (partition by id, date order by rownum1 desc) as rownum2
from tempFirst
)
select id, date, value from tempFirst where rownum1 = 1
union
select id, date, value from tempLast where rownum2 = 1
I have tested the output, which is:
ID DATE VALUE
001 2009-04-23 APPLE
001 2009-04-23 ROSE
001 2009-04-24 BERRY
001 2009-04-24 SILVER

Resources