SQL Server Get row value when using MAX - sql-server

I have a table which holds a date field and an integer field like the example below:
Date Number
01/01/2017 9
02/01/2017 13
03/01/2017 16
04/01/2017 2
15/01/2017 4
20/01/2017 8
27/01/2017 1
I want to write a query selecting the MAX(date) where the date is <= 13/01/2017 (which would give me 04/01/2017) and return the number column value associated with it (2 in this example).. I can of course write 2 queries getting one and using the result to find the next but I hope there is another way using only one statement. It probably would help if I knew how to word this so I haven't had much luck searching for a solution..
Thank you in advance..
Derek

Use TOP 1 and Order By
select Top 1 * from yourtable where [date] <= CONVERT(DATE, '13/01/2017', 103)
order by date desc
Better to use yyyy-mm-dd format for your date input

Related

How to use the datebucket filter

Trying to use the :datebucket filter but it doesn't seem to work.
select date, address from database.table where address = 'xyz' group by :datebucket(date)
This returns the error that date isn't in the group by statement, but it is. If it add it separately to the group by statement, it just groups by the individual date instead of respecting the date bucket selection.
Not finding anything in the Snowflake documentation about how this filter is suppose to work, just that it exists.
In this site: https://www.webagesolutions.com/blog/querying-data-in-snowflake was example like this about databucket function
SELECT COUNT(ORDER_DATE) as COUNT_ORDER_DATE, ORDER_DATE
FROM ORDERS
GROUP BY :datebucket(ORDER_DATE), ORDER_DATE
ORDER BY COUNT_ORDER_DATE DESC;
So could your query work if it was modified like this:
SELECT
date,
address
FROM
database.table
WHERE
address = 'xyz'
GROUP BY :datebucket(date), date
Datebucket is truncating the date, to buckets. But you have selected the raw date.
This is like grouping by decade '60,'70,'80 of what great years, but want the actual year.
SELECT column1 as year,
truncate(year,-1) as decade
FROM VALUES (1),(2),(3),(14),(15),(16),(27),(28),(29);
gives:
YEAR
DECADE
1
0
2
0
3
0
14
10
15
10
16
10
27
20
28
20
29
20
so if I try select
SELECT column1 as year
FROM VALUES (1),(2),(3),(14),(15),(16),(27),(28),(29)
GROUP BY truncate(year,-1)
ORDER BY 1;
gives the error
Error: 'VALUES.COLUMN1' in select clause is neither an aggregate nor in the group by clause. (line 15)
So if we move the decade into the selection, it makes sense:
SELECT truncate(column1,-1) as decade
FROM VALUES (1),(2),(3),(14),(15),(16),(27),(28),(29)
GROUP BY decade
ORDER BY 1;
and we get the
DECADE
0
10
20
So the problem is not :datebucket(date) but the fact while :datebucket(date) and date are related, from the perspective of GROUPING they are unrelated.
I've been trying to use datebucket(date) and daterange, and I also needed the results in a Snowflake graph.
It was a bit trick, because the value returned by datebucket(date) is actually a truncated date based on the selected date part. For that, I had to convert it to a char, and it worked!
select
to_char(:datebucket(start_time), 'YYYY.MM.DD # HH24') as start_time_bucket,
sum(credits_used) as credits_used
from snowflake.account_usage.warehouse_metering_history wmh
where
start_time = :daterange
group by :datebucket(start_time)
And if you're an ACCOUNTADMIN, you can now use the query to get the total credits usage by date :)
Last, to answer the main query by Tony, the query should be:
select date, address
from database.table
where address = 'xyz'
group by :datebucket(date), date, address
// or
select :datebucket(date), address
from database.table
where address = 'xyz'
group by :datebucket(date), address
Try adding the :datebucket(date) in the select part as well (not only in group by). Also, you will probably need an aggregate function for the field address (for example any_value(address):
select :datebucket(date), any_value(address)
from database.table
where address = 'xyz'
group by :datebucket(date)

SQL Server: Find the number of substring occurrences of converted data

I have a huge amount of data and I want to count the number of occurrence for a certain column. What makes this confusing is that it is not just finding the same value of the column, but only part of it.
My table contains TimeStamp in format of (YYYY-MM-DD HH:MM:SS), and I want to apply this SQL command only to YYYY-MM-DD part and count the number of occurrence of each based on that. For example, if my data are as follows:
ID|TimeStamp
--+--------------------
00|2017-08-31 09:00:00
01|2017-08-31 11:00:00
02|2017-08-31 16:30:00
03|2017-08-31 22:00:00
04|2017-09-01 09:00:00
05|2017-09-01 23:40:00
06|2017-09-02 10:30:00
07|2017-09-02 13:00:00
08|2017-09-02 23:00:00
then I want my SQL command to output something like
TimeStamp | Occurrences
-----------+------------
2017-08-31 | 4
2017-09-01 | 2
2017-09-02 | 3
I have been trying to get there from what I have so far but I haven't had luck.
I have this SQL :
SELECT
TimeStamp, COUNT(*)
FROM
myTableName
GROUP BY
TimeStamp
ORDER BY
COUNT(*) DESC -- to sort the occurrence count
but this only counts exactly same timestamps, so this doesn't output what I want it to output. I am also thinking TimeStamp has DateTime type, so I had to convert it to varchar or something first and get the substring of it.
I tried converting the TimeStamp data type to Varchar, and then get the first 10 letters of the string, so
SELECT
COUNT(*) TimeStamp
FROM
myTableName
GROUP BY
(SELECT LEFT(CONVERT(Varchar, TimeStamp, 120), 10))
ORDER BY COUNT(*) DESC
but this causes an error:
Error: Cannot use an aggregate or a subquery in an expression used for the group by list of a GROUP BY clause
Can someone please help me with this? Thank you.
SELECT CAST(TimeStamp as date), COUNT(*)
FROM myTableName
GROUP BY CAST(TimeStamp as date)
ORDER BY 2 DESC

SQL update based on query results with two parameters

I've created a virtual table in SQL Server that has 28 days from the current date and each date has rows for time that range from 12-10 pm incremented by 15 min and another value to indicate that it's turned on/off for availability, so it would be something like this:
date time onoff
-------------------------------------------------
2015-04-08 12:00 1
2015-04-08 12:15 1
....continue until 22:00 then start next day
2015-04-09 12:00 1
..... continue for 28 days
I'd like to update the availability based on a query from another table which would return the date, start and end time...
So far I came up with this
update table1
set onoff = 0
where tbl1date in (select tbl2date from table2 where userid = 1)
The problem I'm having is adding in the between certain hours part of the equation and I'm not sure how to do something like this in SQL or how to even search for the answer based on not being able to word it properly...
Can someone help or point me in the right direction?
use a DATETIME, don't use separate DATE and TIME fields.
I think you should take a look at DATEDIFF (https://technet.microsoft.com/pl-pl/library/ms189794(v=sql.110).aspx) function.
Your where query could look like this:
update table1 set onoff = 0
where
DATEDIFF(minute, <MIN_RANGE>, tbl1date) >= 0 and
DATEDIFF(minute, tbl1date, <MAX_RANGE>) >= 0
How you calculate MIN_RANGE and MAX_RANGE depends on your table2 structure.
As suggested, if you have control over the structure, use datetime fields as they are easier to do the comparisons on. I'm going to assume you don't have control over the structure.
In order to compare the datetimes you need to create them from your separate date and times. You can either parse the time field for the hours and minutes and use DATEADD to add the appropriate offsets to the date, or you can use CONVERT to interpret a date time string as a date. Something like
CONVERT(datetime, SUBSTRING(CONVERT(varchar, tbl1date, 121), 1, 10) + ' ' + tbl1time, 121)
What this does is to convert the date to odbc cannonical format and throwaway the time part as it takes only the first 10 characters. Then it appends the time and interprets the whole string as a odbc cannonical datetime string. That format is yyyy-mm-dd hh:mi:ss.mmm. The hours are based on 24 hours. So if your times are in AM/PM format you're going to have to convert them.
If your other table has separate date and times you'd use a similar expression to combine them.
Once you have the datetimes you can do something like this
UPDATE table1
SET onoff = 0
WHERE <expression above> BETWEEN (SELECT min_value FROM table2) AND (SELECT max_value FROM table2)

SQL SELECT DISTINCT for dynamic data

Need a little help if possible:
Got data as follows , but this is filtered , the INQUIRYID column is what i am trying to work with as this is the Inquiry Number of the booking:
The last column has the number of nights in I am trying to calculate using Excel 2007.
The Column INQ_DATE are the booked nights for the hotel stay , in this case , this enquiry is for 2 nights. Each booking has the amount of lines on it which equals the amount of nights they are staying for.
A second booking is as follows:
7 lines - INQUIRYID = 9501
This booking is for 7 nights , which differs from the first one above of 2 nights.
In the column at the end , i need to calculate the nights , on the filtered data .
there are two tables involved :
BOOKING_INQUIRY
BOOKING_INQUIRY_ROOMS
Linked on : INQUIRYID
So far i have:
In SQL(Which works but has specified a specific INQUIRYID)
SELECT DISTINCT COUNT(INQUIRYID)FROM dbo.BOOKING_INQUIRY_ROOMS
WHERE
inquiryid = '9501'
This returns 7
I know i am nearly there and need to adapt the WHERE clause , to maybe a dynamic parameter , but cant for the life of me how...
Can anyone help me please?
Thanks,
Matt
SELECT
inquiryid,
COUNT(*) as Nights
FROM
dbo.BOOKING_INQUIRY_ROOMS
GROUP BY
inquiryid
Just use GROUP BY...

How do i find the total number of records created on a given day using T-SQL?

I need to find out the total number of records that were created on a given day.
e.g.
ID CreatedDate
1 17/07/2009
2 12/07/2009
3 17/07/2009
4 05/07/2009
5 12/07/2009
6 17/07/2009
Output:
3 Records were created on 17/07/2009
2 Records were created on 12/07/2009
1 Record was created on 05/07/2009
EDIT
Upon testing the second suggestion made by Chris Roberts of including the formatting in the SQL i get this error:
Syntax error converting the varchar value ' Records were created on ' to a column of data type int.
Does anyone know how to rework the solution so that it works?
You should be able to get the data you're after with the following SQL...
SELECT COUNT(ID), CreatedDate
FROM MyTable
GROUP BY CreatedDate
Or - if you want to do the formatting in the SQL, too...
SELECT CONVERT(varchar, COUNT(ID)) + ' Records were created on ' + CONVERT(varchar, CreatedDate)
FROM MyTable
GROUP BY CreatedDate
Good luck!
Is the column actually a timestamp? In which case you will need to apply a function to remove the time component, e.g.:
SELECT COUNT(*), date(CreatedDate) FROM MyTable GROUP BY date(CreatedDate)
I don't know what the function is in T-SQL, it's date() in MySQL and trunc() in Oracle. You may even have to do a to_string and remove the end of the string and group by that if you lack this.
Hope this helps.
select count(*), CreatedDate from table group by CreatedDate order by count(*) DESC

Resources