SQL - Most Common Day of Week Query - sql

I am trying to query on which day of the week most orders occur. I have written a query that returns a result. But, the result is, I believe, the day of the week possibly based on most orders, but the day for every order, so there are dozens. I am wondering how to only return the one day.
The table is:
Orders
OrderID
OrderDate
SELECT MAX(DAYNAME(OrderDate)) as WeekDay
FROM Orders O
GROUP BY OrderDate
OrDER BY WeekDay DESC;

The query you are trying to write is:
SELECT TOP (1) DAYNAME(OrderDate) as WeekDay, COUNT(*)
FROM Orders O
GROUP BY DAYNAME(OrderDate)
OrDER BY COUNT(*) DESC;
Although this query appears to answer your question, you have to be very careful. After all, if Orders had only one day's worth of data, then that day of the week would predominate. My suggestion would be to take data from a specified number of weeks -- preferably with no holidays -- to get this information.
Your question doesn't specify the database (although I could guess). The specific date/time logic for this depends on the database.

This will let you know how many orders were placed on which day.
SELECT
DAYNAME((OrderDate)) AS dayofweek, COUNT(OrderID) AS ordered
FROM
Orders
GROUP BY dayofweek
ORDER BY ordered DESC;

Related

Find the average number of orders placed per month for each category of an item sold

trying to work the below on big query. can anyone tell me where i am going wrong.
also the date is in timestamp
SELECT (COUNT(Items_purchased])) / (SELECT COUNT(Order_id) FROM table where Order_id IS NOT NULL) OVER (ORDER BY Order_date)
FROM table
GROUP BY Items_purchased, Order_date
tried using the avg function itself, but bq has been throwing errors even when checking for avg no of orders paced per item.

Delete duplicates using dense rank

I have a sales data table with cust_ids and their transaction dates.
I want to create a table that stores, for every customer, their cust_id, their last purchased date (on the basis of transaction dates) and the count of times they have purchased.
I wrote this code:
SELECT
cust_xref_id, txn_ts,
DENSE_RANK() OVER (PARTITION BY cust_xref_id ORDER BY CAST(txn_ts as timestamp) DESC) AS rank,
COUNT(txn_ts)
FROM
sales_data_table
But I understand that the above code would give an output like this (attached example picture)
How do I modify the code to get an output like :
I am a beginner in SQL queries and would really appreciate any help! :)
This would be an aggregation query which changes the table key from (customer_id, date) to (customer_id)
SELECT
cust_xref_id,
MAX(txn_ts) as last_purchase_date,
COUNT(txn_ts) as count_purchase_dates
FROM
sales_data_table
GROUP BY
cust_xref_id
You are looking for last purchase date and count of distinct transaction dates ( like if a person buys twice, it should be considered as one single time).
Although you mentioned you want count of dates but sample data shows you want count of distinct dates - customer 284214 transacted 9 times but distinct will give you 7.
So, here is the SQL you can use to get your result.
SELECT
cust_xref_id,
MAX(txn_ts) as last_purchase_date,
COUNT(distinct txn_ts) as count_purchase_dates -- Pls note distinct will count distinct dates
FROM sales_data_table
GROUP BY 1

Efficiently find last date in a table - Teradata SQL

Say I have a rather large table in a Teradata database, "Sales" that has a daily record for every sale and I want to write a SQL statement that limits this to the latest date only. This will not always be the previous day, for example, if it was a Monday the latest date would be the previous Friday.
I know I can get the results by the following:
SELECT s.*
FROM Sales s
JOIN (
SELECT MAX(SalesDate) as SalesDate
FROM Sales
) sd
ON s.SalesDate=sd.SalesDt
I am not knowledgable on how it would process the subquery and since Sales is a large table would there be a more efficient way to do this given there is not another table I could use?
Another (more flexible) way to get the top n utilizes OLAP-functions:
SELECT *
FROM Sales s
QUALIFY
RANK() OVER (ORDER BY SalesDate DESC) = 1
This will return all rows with the max date. If you want only one of them switch to ROW_NUMBER.
That is probably fine, if you have an index on salesdate.
If there is only one row, then I would recommend:
select top 1 s.*
from sales s
order by salesdate desc;
In particular, this should make use of an index on salesdate.
If there is more than one row, use top 1 with ties.

Make table ID appear as a column and select across all tables

I've been requested by my superiors to write a query that will search every table in a database (each representative of a road and their total counts of traffic) and take the total counts by hour of motorcycles. Here's what I have so far whilst testing on one table:
WITH
totalCount AS
(
SELECT DATEDIFF(dd,0,event_time) AS DaySerial,
DATEPART(dd,event_time) AS theDay,
DATEDIFF(mm,0,event_time) AS MonthSerial,
DATEPART(mm,event_time) AS MonthofYear,
DATEDIFF(hh,0,event_time) AS HourSerial,
DATEPART(hh,event_time) AS Hour,
COUNT(*) AS HourlyCount,
DATEDIFF(yy,0,event_time) AS YearSerial,
DATEPART(yy,event_time) AS theYear
FROM [RUD].dbo.[10011E]
WHERE length <='1.7'
GROUP BY DATEDIFF(hh,0,event_time),
DATEPART(hh,event_time),
DATEDIFF(dd,0,event_time),
DATEPART(dd,event_time),
DATEDIFF(mm,0,event_time),
DATEPART(mm,event_time),
DATEDIFF(yy,0,event_time),
DATEPART(yy,event_time)
)
SELECT
theYear,
MonthofYear,
theDay,
Hour,
AVG(HourlyCount) AS Avg_Count
FROM
totalCount
GROUP BY
theYear,
MonthofYear,
theDay,
Hour
ORDER BY
theYear,
MonthofYear,
theDay,
Hour
Now I'm sure some of this is redundant or not needed, that's ok for now (I'm new to SQL btw, which is why some of this will be redundant). Basically as it stands, I list the year, month, date, hour and hourly count of motorcycles for one road. Now my two questions:
How do I take this query and make it so that it searches across every single table in the RUD database? Do I just need to list them all and UNION them, or is there a quicker way?
I realise if I search through every table gathering only the above (year, month, day, hour, hourly count) I will end up with the right data but with no way to distinguish which road all the counts are coming from. Is there a way to select the table ID (in this example, 10011E is the ID, and is the assigned name for a specific road) and place it in a column next to the rows that were selected from it?
If anyone needs clarification on what I mean, please let me know! Thanks!
One option would be to use UNION ALL and add an additional column for which source. You'll have to write out each of your tables in this case, but it's perhaps your fastest option:
SELECT ID, 'YourTable' TableName
FROM YourTable
UNION ALL
SELECT ID, 'YourOtherTable'
FROM YourOtherTable
....
Alternatively, dynamic sql could produce you the same results -- you might not have to type out all your table names, but it comes with a performance hit.

help with getting statistics from db in SQL

I'm using SQL-Server 2005.
I have two tables Users and Payments which has a foreign key to Users.
Both Users and Payments have a date column (Users set their value during registration and Payments gets a value during payment). Users has a column called isPaymentsRecurring as bit which tells me to renew the user or not. The value is 1 on default = recurring. Payments has a column called paymentSum as tinyint where I insert the value of payment. ( first payment is equal to recurring one)
I need to get a few statistics about that for simple line chart, grouped by date. To separate single days I use the hack below to get whole day as a single item.
Day hack
dateadd(dd,datediff(dd,0,date),0)
What I need to get are the values below all must be grouped by day hack.
1.Unique users in system per day
2.Users that ordered once and then set isPaymentRecurring to 0.
3.Sum of paymentSum per day
4.How many users got recurring payment per day. This means orders of user per day except first order in system.
Thanks, I have queries that work but they don't work as I want them to thus I want pros opinion on that.
You could add computed columns to your Payments and Users tables that represent the day, month and year of payment or user registration:
ALTER TABLE dbo.Payments
ADD PaymentDay AS DAY(PaymentDate) PERSISTED,
PaymentMonth AS MONTH(PaymentDate) PERSISTED,
PaymentYear AS YEAR(PaymentDate) PERSISTED
Now these columns give you INT values for the day, month and year and you can easily query them. Since they're persisted, they can even be indexed!
You can easily group your payments by those columns now:
SELECT (list of fields), COUNT(*)
FROM dbo.Payments
GROUP BY PaymentYear, PaymentMonth, PaymentDay
or whatever you need to do. With this approach, you can also easily do stats on a per-month basis, e.g. sum up all payments and group by month.
Update: ok, so you need to understand how to create those queries:
Unique users in system per day
SELECT UserDay, UserMonth, UserYear, COUNT(*)
FROM dbo.Users
GROUP BY UserDay, UserMonth, UserYear
That would count the users and group them by day, month, year
Users that ordered once and then set isPaymentRecurring to 0.
SELECT UserDay, UserMonth, UserYear, COUNT(*)
FROM dbo.Users
WHERE isPaymentRecurring = 0
GROUP BY UserDay, UserMonth, UserYear
Is that what you're looking for?? Number of users grouped by day/month/year that have their isPaymentRecurring set to 0 ?
sum of paymentSum per day
SELECT PaymentDay, PaymentMonth, PaymentYear, SUM(PaymentSum)
FROM dbo.Payments
GROUP BY PaymentDay, PaymentMonth, PaymentYear
That would sum up the PaymentSum column and group it by day, month, year
I don't really understand what you're trying to achieve with the other two queries, and what criteria would have to apply for those queries.