I have a query, where I need the MIN of a DateTime field and then I need the value of a corresponding field in the same row.
Now, I have something like this, however I cannot get Price field without putting it also in an aggregate clause, which is not what I want.
SELECT MIN([Registration Time]), Price FROM MyData WHERE [Product Series] = 'XXXXX'
I need the MIN of the Registration Time field and then I just want the corresponding Price field for that row, however how do I show that?
I do also need my WHERE clause as shown.
I'm sure I've overlooked something really obvious. Using SQL Server 2008
If you want just one record with [Registration Time], Price, it'd be as simple as this:
select top 1 [Registration Time], Price
from MyData
where [Product Series] = 'XXXXX'
order by [Registration Time]
If you want minimum [Registration Time] and corresponding Price for all [Product Series], then there's a few approaches, for example, using row_number() function:
with cte as (
select
[Registration Time], Price,
row_number() over(partition by [Product Series] order by [Registration Time]) as rn
from MyData
)
select
[Registration Time], Price, [Product Series]
where rn = 1
Related
I am running SQL Server 2008 R2 (RTM).
I have a SQL query that pulls Dates, Products, Customers and Units:
select
[Transaction Date] as Date,
[SKU] as Product,
[Customer Name] as Customer,
sum(Qty) as Units
from dataset
where [Transaction Date] < '2019-03-01' and [Transaction Date] >= '2016-01-01'
group by [Transaction Date], [SKU], [Customer Name]
order by [Transaction Date]
This pulls hundreds of thousands of records and I wanted to determine if a certain transaction was a new order or reorder based on the following logic:
Reorder: That specific Customer has ordered that specific product in the last 6 months
New Order: That specific Customer hasn’t ordered that specific product in the last 6 months
For that I have this formula in Excel that seems to be working:
=IF(COUNTIFS(A$1:A1,">="&DATE(YEAR(A2),MONTH(A2)-6,DAY(A2)),C$1:C1,C2,B$1:B1,B2),"Reorder","New Order")
The formula works when I paste it individually or in a smaller dataset, but when I try to copy paste it to all 500K+ rows, Excel gives up because it loops for each calculation.
This could probably be done in SQL, but I don’t have the knowledge on how to convert this excel formula to SQL, I just started studying it.
You're doing pretty well with the start of your query there. There are three additional functions you're looking to add to your query.
The first thing you'll need is the easiest. GETDATE() simply returns the current date. You'll need that when you're comparing the current date to the transaction date.
The second function is DATEDIFF, which will give you a unit of time between two dates (months, days, years, quarters, etc). Using DATEDIFF, you can say "is this date within the last 6 months". The format for this is pretty easy. It's DATEDIFF(interval, date1, date2).
The thrid function you're looking for is CASE, which allows you to tell SQL to give you one answer if one condition is met, but a different answer if a different condition is met. For your example, you can say "if the difference in days is < 60, return 'Reorder', if not give me 'New Order'".
Putting it all together:
SELECT CASE
WHEN DATEDIFF(MONTH, [Transaction Date], GETDATE()) <= 6
THEN 'Reorder'
ELSE 'New Order'
END as ORDER_TYPE
,[Transaction Date] AS DATE
,[SKU] AS PRODUCT
,[Customer Name] AS CUSTOMER
,Qty AS UNITS
FROM DATASET
For additonal examples on CASE, take a look at this site: https://www.w3schools.com/sql/sql_ref_case.asp
For additional examples on DATEDIFF, take a look here: See the
following webpage for examples and a chance to try it out:
https://www.w3schools.com/sql/func_sqlserver_datediff.asp
SELECT CASE
WHEN Datediff(day, [transaction date], Getdate()) <= 180 THEN 'reorder'
ELSE 'Neworder'
END,
[transaction date] AS Date,
[sku] AS Product,
[customer name] AS Customer,
qty AS Units
FROM datase
If I understand correctly, you want to peak at the previous date and make a comparison. This suggests lag():
select (case when lag([Transaction Date]) over (partition by SKU, [Customer Name] order by [Transaction Date]) >
dateadd(month, -6, [Transaction Date])
then 'Reorder'
else 'New Order'
end) as Order_Type
[Transaction Date] as Date,
[SKU] as Product,
[Customer Name] as Customer,
sum(Qty) as Units
from dataset d
group by [Transaction Date], [SKU], [Customer Name];
EDIT:
In SQL Server 2008, you can emulate the LAG() using OUTER APPLY:
select (case when dprev.[Transaction Date] >
dateadd(month, -6, d.[Transaction Date])
then 'Reorder'
else 'New Order'
end) as Order_Type
d.[Transaction Date] as Date,
d.[SKU] as Product,
d.[Customer Name] as Customer,
sum(d.Qty) as Units
from dataset d outer apply
(select top (1) dprev.*
from dataset dprev
where dprev.SKU = d.SKU and
dprev.[Customer Name] = d.[Customer Name] and
dprev.[Transaction Date] < d.[Transaction Date]
order by dprev.[Transaction Date] desc
) dprev
group by d.[Transaction Date], d.[SKU], d.[Customer Name];
I have my query:
SELECT [Shipment Date], [Amount] as [Running Costs], Sum([Amount]) OVER
(ORDER BY [Shipment Date]) as [Total Running Costs]
FROM...
This gets me 3 columns:
Shipment Date | Running Costs | Total Running Costs
I would like to add a fourth column to this query which has the same value for all rows, and the same number of rows as my original query results.
I know you could add for example '999'as Something to the search results, but how can I do the same for a sum of another column (example: Imagine the total sum of the a column in another table is 1500, and I want to have 1500 for all rows in the fourth column. Something like select sum(column_name)?
The database engine is MSSQL.
You can use a nested query
SELECT [Shipment Date], [Amount] as [Running Costs], [Total Running Costs], SUM([Total Running Costs] OVER ())
FROM
(
SELECT [Shipment Date], [Amount] as [Running Costs], Sum([Amount]) OVER
(ORDER BY [Shipment Date]) as [Total Running Costs]
FROM...
)
Nested window function should also work
SUM(SUM([Running costs]) OVER (ORDER BY [Shipment Date])) OVER ()
Good day,
I have an SQL code that return to me all quantities that I received over time, but I want to display only the latest one
SELECT * FROM
(SELECT DISTINCT
[dbo].[ttcibd001110].[t_cmnf] AS [Manufacturer],
[dbo].[ttcibd001110].[t_item] AS [Item code],
[dbo].[ttcibd001110].[t_dsca] AS [Description],
[dbo].[ttcibd001110].[t_seak] AS [Search key 1],
[dbo].[twhinr110110].[t_trdt] AS [Transaction date],
[dbo].[twhinr110110].[t_cwar] AS [Warehouse],
[dbo].[twhinr110110].[t_qstk] AS [Quantity Inventory Unit]
FROM [dbo].[twhinr110110] LEFT JOIN [dbo].[ttcibd001110]
ON [dbo].[twhinr110110].[t_item]=[dbo].[ttcibd001110].[t_item]
WHERE [dbo].[twhinr110110].[t_koor]='2' AND [dbo].[ttcibd001110].[t_cmnf]='ManufacturerX') AS tabel
WHERE ltrim(tabel.[Item code])='1000045'
Now, from this selection I want to select only the line with the latest Transaction date, but I am stuck.
Can somebody help me in this way?
Thank you!
Change your beginning to
SELECT TOP 1
and after where use
ORDER BY [Transaction date] DESC
I'm using Advantage Database Server by Sybase. I need to elimiate duplicate addbatch's from my report, but having trouble pulling up just distinct records. Any idea what I am missing?
here is what I am using
SELECT DISTINCT
SI.[addbatch] as [Batch#],
SI.[current account #] as [Account],
SI.[status date] as [Status Date],
SI.[SKU] as [SKU],
AC.[email address] as [Email]
FROM salesinventory SI, accounts AC
WHERE AC.[account #]=SI.[current account #] and [Status Date] > '6/1/2015'
I still get duplicate addbatch's though. I'm not sure where I am going wrong! Thanks in advance! Wasn't even sure how to google this question!
The problem is that you need to check uniqueness of a single column and that's not actually what your code is performing. Try this
SELECT *
FROM (SELECT SI.[addbatch] as [Batch#],
SI.[current account #] as [Account],
SI.[status date] as [Status Date],
ETC,
ROW_NUMBER() OVER (PARTITION BY [Batch#]) AS RowNumber
FROM salesinventory SI, accounts AC
WHERE AC.[account #]=SI.[current account #] and [Status Date] > '6/1/2015') as rec
WHERE rec.RowNumber = 1
-- The following code is generic to de-duplicate records, modify to suit your need.
select x.[Well_Name] as nameX
, x.[TestDate] as dateX
from (
SELECT count(*) as dup
,[Well_Name]
,[TestDate]enter code here
FROM [dbo].[WellTests]
group by [TestDate] ,[Well_Name] ) x
where dup > 1
If you want to have unique batch numbers in your result, you have to GROUP BY the batch field only.
Something like this should work:
SELECT
SI.[addbatch] as [Batch#],
MIN(SI.[current account #]) as [Account],
MIN(SI.[status date]) as [Status Date],
MIN(SI.[SKU]) as [SKU],
MIN(AC.[email address]) as [Email]
FROM salesinventory SI, accounts AC
WHERE AC.[account #]=SI.[current account #] and [Status Date] > '6/1/2015'
GROUP BY
SI.[addbatch]
You didn't say how you want to aggregate the other columns, just replace MIN with something that makes more sense for you, like SUM or COUNT, etc.
There is a topic about grouping in the documentation.
PS: SELECT DISTINCT is (basically) just a shorter way to GROUP BY on all columns without any aggregation.
I have a table with following format
Now i am using Access and want to create a table which will provide me sum of units where Segment is commercial, at the same time I just want to sum Subregions where they are same..means MCA+MCA+MCA... Also the period should be same where we have added them..means 2013Q1 should be added too 2013Q1 only and grouped in that format.
Something like below
Thanks and Regards
The following query totals the unit while grouping on the other fields. To change the range that it totals over, you will either be adding a WHERE clause or you will change the fields that it is GROUP BY
SELECT [Sub Region], [Corporate Family], [HP Segment], [Product Category], [Period], Sum([Units])
FROM TableName
GROUP BY [Sub Region], [Corporate Family], [HP Segment], [Product Category], [Period]