How to find the Longest Booking ID for the given two dates and Costliest Booking ID for the given cost.
Here we have the 13 days difference so we are getting the longest booking id as 1.
what are the approach to archive this using sql query.
this will work:
(SELECT 'Total Booking Count' AS Label, COUNT(*) AS Value FROM bookings)
UNION ALL
(SELECT 'Longest Booking Id', booking_id FROM bookings ORDER BY DATEDIFF(enddate, startdate) DESC LIMIT 1)
UNION ALL
(SELECT 'Costliest Booking Id', booking_id FROM bookings ORDER BY (tariff*DATEDIFF(enddate, startdate)) DESC LIMIT 1)
with data
as (select *
,row_number() over(order by datediff(dd,end_date,start_date) desc) as rnk_time
,row_number() over(order by tarrif desc) as rnk_cost
,count(*) over(partition by 1) as tot_cnt
from your_table
)
select 'Total Booking count',tot_cnt
from data
where rnk_time=1
union all
select 'Longest Booking id',booking_id
from data
where rnk_time=1
union all
select 'Costliest Booking id',booking_id
from data
where rnk_cost=1
Related
I have the transaction table with the following columns :
TRANSACTION_ID, USER_ID, MERCHANT_NAME, TRANSACTION_DATE, AMOUNT
-)Query to calculate time difference (in days) between current and previous order of
each customer
-)the avg time difference between two orders for every
customer.
Note : Exclude users with single transactions
I tried the following code to get the 1st part of the query but it looks too messy
with t1 as
(Select USER_ID,TRANSACTION_DATE,Dense_rank() over(partition by USER_ID order by TRANSACTION_DATE desc) as r1
from CDM_Bill_Details
order by USER_ID, TRANSACTION_DATE desc)
Select t11.USER_ID, datediff(t11.TRANSACTION_DATE,t111.TRANSACTION_DATE) from t1 as t11,t1 as t111
where (t11.r1=1 and t111.r1=2) and (t11.USER_ID=t111.USER_ID)
Please try this:
with t2 as (select *,
lag(t1.TRANSACTION_DATE, 1) OVER (PARTITION BY USER_ID ORDER BY TRANSACTION_DATE) AS previous_date,
datediff(t1.TRANSACTION_DATE, lag(t1.TRANSACTION_DATE, 1) OVER (PARTITION BY USER_ID ORDER BY TRANSACTION_DATE)) AS diff_prev_curr
from CDM_Bill_Details t1)
select *,
avg(diff_prev_curr) OVER (PARTITION BY USER_ID) AS avg_days_diff
from t2
where previous_date is not null
Below is a SQL query problem for which I am not able to understand correct approach:
DB tables:
Employee: emp_id, emp_name
Credit: credit_id, emp_id, credit_date, credit_amount
debit: debit_id, emp_id, debit_date, debit_amount
Here, each person can have multiple incomes and expenses.
Query requirement: At the end of each day, each employee will have some asset('credit till now' - 'debit till now'). We need to find top five employees in terms of maximum asset and the date on which they had this maximum asset.
I have tried the below query but seems like I am missing something:
select Credit.emp_id, Credit.date, (Credit.income_amount - Debit.credit_amount) from
(select emp_id, sum(amount) as credit_amount
from credit) Credit
LEFT JOIN LATERAL (
select emp_id, sum(amount) as debit_amount
from debits
where debits.emp_id = Credit.emp_id and Credit.date >= debits.date
group by debits.emp_id
) Debit
ON true
Here I'm breaking the query to make it more readable.
First of all, we need to get the total amount on a day-level for both credit and debit both, so that we can join the credit and debit table on the day level with the same emp_id.
with
credit as(
select emp_id,credit_date date,sum(credit_amount) as amount
from credit
group by 1,2),
debit as(
select emp_id,debit_date,sum(debit_amount) as amount
from expenses
group by 1,2),
Now we need to full outer join the "credit" and "debit" subqueries
payments as (
select distinct
case when c.emp_id is null then d.person_id else c.emp_id end as emp_id ,
case when c.emp_id is null then d.date else c.date end as date,
case when c.emp_id is null then 0 else i.amount end as credit ,
case when d.emp_id is null then 0 else d.amount end as debit
from credit c
full outer join debit d on d.emp_id=c.emp_id and d.date=c.date
),
Now we will take day-wise cumulative sum for credit, debit and total balance as shown below.
total_balance as(
SELECT emp_id, date,
sum(credit) OVER (PARTITION BY emp_id ORDER BY date asc) AS total_credit,
sum(debit) OVER (PARTITION BY emp_id ORDER BY date asc) AS total_debit,
(sum(income) OVER (PARTITION BY person_id ORDER BY date asc) -
sum(expense) OVER (PARTITION BY person_id ORDER BY date asc)) as total_balance
FROM group_payment
ORDER BY person_id, date),
Now we need to use the rank() function to assign rank based on total balance (desc) for an emp_id (ie. rank=1 will be assigned to the largest total balance on a day for a particular emp_id). The query is shown below.
ranks as (select emp_id,date,total_balance,
rank() over (partition by emp_id order by total_balance desc) as rank
from total_balance ),
Now pick the rows having rank=1 (ie. MAX of total_balance on a day for an emp_id and the date on which it was MAX).
Order it by total_balance descending and pick the top 5 rows
emp_order as (select emp_id,date,total_balance
from ranks
where rank=1
order by 3 desc
limit 5)
Now pick the name from the employee table.
select emp_id,name, date, total_balance as balance
from emp_order eo
join Employee e on e.emp_id = eo.emp_id
order by 4 desc
Group by and sum allows you to get the total credit for each person into 1 record. You can do a similar thing in a subquery to subtract the debit.
Select top 5 emp_id, credit_date, (sum(credit_amount) -
(select sum(debit_amount) from debit d
where c.emp_id = d.emp_id and c.credit_date = d.debit_date)
) as total
from Credit c group by emp_id, credit_date order by total
New to SQL. Can someone please tell me if my SQL query is correct? I am trying to find out how much each unique customer spent on their most recent transaction.
Table Name: Expenditure
Columns:
1. created_time
2. customer_id
3. spend
SELECT
distinct(customer_id), sum(spend)
FROM
Expenditure
WHERE
created_time =
(SELECT MAX(created_time))
FROM
Expenditure
GROUP BY
distinct(customer_id)
If you are using MySQL 8+, then I prefer to use window functions here:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY created_time DESC) rn
FROM Expenditure
)
SELECT customer_id, created_time, spend
FROM cte
WHERE rn = 1;
To correct the approach you were trying to use, you can correlate the subquery to the outer query by customer:
SELECT customer_id, created_time, spend
FROM expenditure e1
WHERE created_time = (SELECT MAX(e2.created_time)
FROM Expenditure
WHERE e2.customer_id = e1.customer_id);
I have a food selling website in which there is order table which record the order of every user.It column for user id ,user name,orderid ,timestamp of order.I want to know the maximum number of order that has been made in any one hour span through out the day.Give me any formula for this,or any algorithm or any sql queries for these.
SQL server:
with CTE as
(
select cast(t1.timestamp as date) as o_date, datepart(hh, t1.timestamp) as o_hour, count(*) as orders
from MyTable t1
group by cast(t1.timestamp as date), datepart(hh, t1.timestamp)
)
select o_date, o_hour, orders
from CTE
where orders = (select max(orders) from CTE)
Oracle
with CTE as
(
select to_char(t1.timestamp, 'YYYYMMDD') as o_date, to_char(t1.timestamp, 'HH24') as o_hour, count(*)
from MyTable t1
group by to_char(t1.timestamp, 'YYYYMMDD'), to_char(t1.timestamp, 'HH24')
)
select o_date, o_hour, orders
from CTE
where orders = (select max(orders) from CTE)
You can get count by day and hour like this
For SQL
SELECT TOP 1
COUNT(*)
FROM myTable
GROUP BY DATEPART(day, [column_date]), DATEPART(hour, [column_date])
ORDER BY COUNT(*) DESC;
For MySQL
SELECT
COUNT(*)
FROM myTable
GROUP BY HOUR(column_date), DAY(column_date)
ORDER BY COUNT(*) DESC
LIMIT 1;
i have a table employee(id,dept_id,salary,hire_date,job_id) . the following query i have to execute.
Show all the employee who were hired on the day of the week on which least no of employee were hired.
i have done the query, but am not able to get the least. please check if am correct.
select id, WEEKDAY(hire_date)+1 as days,count(WEEKDAY(hire_date)+1) as count
from test.employee group by days
This should get you the weekday on which the least number of employees were hired:
SELECT
count(id) as `Total`,
WEEKDAY(hire_date) as `DoW`
FROM
test.employee
GROUP BY `DoW`
ORDER BY `Total` DESC LIMIT 1;
select id from test.employee where hire_date in
( select count(id) count,hire_date
from test.employee
order by count desc
limit 1)
this should work
You may try this, as it will not limit to one record if you have multiple week days where the same least number of employees were hired. In reality it makes sense. The following is based on sample data.
Query:
-- find minimum id count
SELECT MIN(e.counts) INTO #min
FROM (SELECT COUNT(*) as counts,
WEEKDAY(hire_date+1) as day
FROM employee
GROUP BY WEEKDAY(hire_date+1)) e
;
-- show weekdays with minimum id counts
SELECT e2.counts as mincount,
WEEKDAY(e1.hire_date+1) as weekday
FROM employee e1
JOIN (SELECT COUNT(id) as counts,
WEEKDAY(hire_date+1) as day
FROM employee
GROUP BY day
HAVING COUNT(*) = #min) e2
ON WEEKDAY(e1.hire_date+1) = e2.day;
Results:
MINCOUNT WEEKDAY
1 6
1 3
1 4
1 2
SQLFIDDLE
select min(id), WEEKDAY(hire_date)+1 as days,count(WEEKDAY(hire_date)+1) as count
from test.employee group by days
SELECT
*
FROM
employee
WHERE
DAYOFWEEK(hire_date)
IN
(
SELECT
weekday
FROM
(
SELECT
count(*) as bcount,
DAYOFWEEK(hire_date) as weekday
FROM
employee as a
GROUP BY
weekday
HAVING
bcount = (
SELECT
MIN(tcount)
FROM
(
SELECT
count(*) as tcount,
DAYOFWEEK(hire_date) as weekday
FROM
employee
GROUP BY
weekday
) as t
)
) as q