I have transactions table with columns id, user_id, currency, amount and created_at;
I want to write function to check in last x days transaction with exist amount repeated or not.
For example user makes transaction per 200$ in 5 days, and 6th days wants to make transaction in 250$. Function have to check did user make transaction in last 5 days per 250$ or not. In this example function have to return false. Because user breaks rule.
If user want to make transaction with 200$ function have to return true;
I have tried with
select count(*) from "transactions" where "created_at" >= NOW()- INTERVAL '5 DAY' and "amount"=250 and "currency" = "USD"
but this gives me incorrect answer, becouse if user makes a transaction twise a day, this function calculates 5 items in 4 day. If n transactions in a day I have to calculate it 1 transaction.
So:
id user_id currency amount created_at
1 1 USD 200 2021-05-15 16:00:01
2 1 USD 200 2021-05-16 18:05:28
3 1 USD 200 2021-05-17 11:33:55
4 1 USD 200 2021-05-18 12:00:01
5 1 USD 200 2021-05-18 13:15:01
6 2 USD 250 2021-05-15 16:00:01
7 2 USD 250 2021-05-16 18:05:28
8 2 USD 250 2021-05-17 11:33:55
9 2 USD 250 2021-05-18 12:00:01
10 2 USD 250 2021-05-19 13:15:01
with this data, query have to return 4 items for user with id 1 and amount 200. Have to return 5 items for user with id 2 and amount 250
I think you just want count(distinct). You seem to want different values for each user, so that suggests group by as well:
select user_id, count(distinct created_at::date) as num_days
from "transactions"
where created_at >= NOW()- INTERVAL '5 DAY' and
amount = 250 and
currency = 'USD'
group by user_id;
Related
I need to show the number of valid inspectors we have by month over the last five years. Inspectors are considered valid when the expiration date on their certification has not yet passed, recorded as the month end date. The below SQL code is text of the query to count valid inspectors for January 2017:
SELECT Count(*) AS RecordCount
FROM dbo_Insp_Type
WHERE (dbo_Insp_Type.CERT_EXP_DTE)>=#2/1/2017#);
Rather than designing 60 queries, one for each month, and compiling the results in a final table (or, err, query) are there other methods I can use that call for less manual input?
From this sample:
Id
CERT_EXP_DTE
1
2022-01-15
2
2022-01-23
3
2022-02-01
4
2022-02-03
5
2022-05-01
6
2022-06-06
7
2022-06-07
8
2022-07-21
9
2022-02-20
10
2021-11-05
11
2021-12-01
12
2021-12-24
this single query:
SELECT
Format([CERT_EXP_DTE],"yyyy/mm") AS YearMonth,
Count(*) AS AllInspectors,
Sum(Abs([CERT_EXP_DTE] >= DateSerial(Year([CERT_EXP_DTE]), Month([CERT_EXP_DTE]), 2))) AS ValidInspectors
FROM
dbo_Insp_Type
GROUP BY
Format([CERT_EXP_DTE],"yyyy/mm");
will return:
YearMonth
AllInspectors
ValidInspectors
2021-11
1
1
2021-12
2
1
2022-01
2
2
2022-02
3
2
2022-05
1
0
2022-06
2
2
2022-07
1
1
ID
Cert_Iss_Dte
Cert_Exp_Dte
1
1/15/2020
1/15/2022
2
1/23/2020
1/23/2022
3
2/1/2020
2/1/2022
4
2/3/2020
2/3/2022
5
5/1/2020
5/1/2022
6
6/6/2020
6/6/2022
7
6/7/2020
6/7/2022
8
7/21/2020
7/21/2022
9
2/20/2020
2/20/2022
10
11/5/2021
11/5/2023
11
12/1/2021
12/1/2023
12
12/24/2021
12/24/2023
A UNION query could calculate a record for each of 50 months but since you want 60, UNION is out.
Or a query with 60 calculated fields using IIf() and Count() referencing a textbox on form for start date:
SELECT Count(IIf(CERT_EXP_DTE>=Forms!formname!tbxDate,1,Null)) AS Dt1,
Count(IIf(CERT_EXP_DTE>=DateAdd("m",1,Forms!formname!tbxDate),1,Null) AS Dt2,
...
FROM dbo_Insp_Type
Using the above data, following is output for Feb and Mar 2022. I did a test with Cert_Iss_Dte included in criteria and it did not make a difference for this sample data.
Dt1
Dt2
10
8
Or a report with 60 textboxes and each calls a DCount() expression with criteria same as used in query.
Or a VBA procedure that writes data to a 'temp' table.
In the project I am currently working on in my company, I would like to show sales related KPIs together with Customer Score metric on SQL / Tableau / BigQuery
The primary key is order id in both tables. However, order date and the date we measure Customer Score may be different. For example the the sales information for an order that is released in Feb 2020 will be aggregated in Feb 2020, however if the customer survey is made in March 2020, the Customer Score metric must be aggregated in March 2020. And what I would like to achieve in the relational database is as follows:
Sales:
Order ID
Order Date(m/d/yyyy)
Sales ($)
1000
1/1/2021
1000
1001
2/1/2021
2000
1002
3/1/2021
1500
1003
4/1/2021
1700
1004
5/1/2021
1800
1005
6/1/2021
900
1006
7/1/2021
1600
1007
8/1/2021
1900
Customer Score Table:
Order ID
Customer Survey Date(m/d/yyyy)
Customer Score
1000
3/1/2021
8
1001
3/1/2021
7
1002
4/1/2021
3
1003
6/1/2021
6
1004
6/1/2021
5
1005
7/1/2021
3
1006
9/1/2021
1
1007
8/1/2021
7
Expected Output:
KPI
Jan-21
Feb-21
Mar-21
Apr-21
May-21
June-21
July-21
Aug-21
Sep-21
Sales($)
1000
2000
1500
1700
1800
900
1600
1900
AVG Customer Score
7.5
3
5.5
3
7
1
I couldn't find a way to do this, because order date and survey date may/may not be the same.
For sample data and expected output, click here.
I think what you want to do is aggregate your results to the month (KPI) first before joining, as opposed to joining on the ORDER_ID
For example:
with order_month as (
select date_trunc(order_date, MONTH) as KPI, sum(sales) as sales
from `testing.sales`
group by 1
),
customer_score_month as (
select date_trunc(customer_survey_date, MONTH) as KPI, avg(customer_score) as avg_customer_score
from `testing.customer_score`
group by 1
)
select coalesce(order_month.KPI,customer_score_month.KPI) as KPI, sales, avg_customer_score
from order_month
full outer join customer_score_month
on order_month.KPI = customer_score_month.KPI
order by 1 asc
Here, we aggregate the total sales for each month based on the order date, then we aggregate the average customer score for each month based on the date the score was submitted. Now we can join these two on the month value.
This results in a table like this:
KPI
sales
avg_customer_score
2021-01-01
1000
null
2021-02-01
2000
null
2021-03-01
1500
7.5
2021-04-01
1700
3.0
2021-05-01
1800
null
2021-06-01
900
5.5
2021-07-01
1600
3.0
2021-08-01
1900
7.0
2021-09-01
null
1.0
You can pivot the results of this table in Tableau, or leverage a case statement to pull out each month into its own column - I can elaborate more if that will be helpful
How would I go about having a separate column that shows the prior week's value? For example, if Product A's value for 01/03/2021 was 100, I would like 01/10/2021 to show its date value as well as the 01/03/2021 value in a separate column.
Desired table below (for simplicity sake I added random numbers for the prior week values for 01/03 and 01/04):
Date
Product
Value
Prior Week Value
01/03/2021
Product A
100
50
01/04/2021
Product A
200
55
01/10/2021
Product A
600
100
01/11/2021
Product A
700
200
01/03/2021
Product B
250
40
01/04/2021
Product B
550
45
01/10/2021
Product B
460
250
01/11/2021
Product B
100
550
If you want exactly 7 days before, you can use window functions with a range specification:
select t.*,
max(value) over (partition by product
order by date
range between '7 day' preceding and '7 day' preceding
) as value_prev_week
from t;
I have the following table named Application in Postgres:
ID JA_ID TO_STATUS FROM_STATUS DATE
1 100 Matched NULL 2019-05-06
2 100 INterview Matched 2019-05-30
3 100 Extended INterview 2019-05-31
4 200 New_Applicant NULL 2020-04-01
5 200 INterview New_applicant 2020-04-05
6 200 Rejected interview 2020-05-10
Now I need to calculate # of days between each status change for every JA_ID from this table.I have sorted the status change based JA_ID and DAte(in asc). My O/P 'DAYS' column should be like this:
ID JA_ID TO_STATUS FROM_STATUS DATE DAYS
1 100 Matched NULL 2019-05-06 NULL
2 100 Interview Matched 2019-05-30 24
3 100 Extended INterview 2019-05-31. 1
4 200 New_Applicant NULL 2020-04-01. NULL
5 200 Interview New_applicant 2020-04-05. 4
6 200 Rejected interview 2020-05-10. 5
Assuming "date" is defined with the datatype date (as it should be), you can use lag() to get the previous date and subtract the values:
select id, ja_id, to_status, from_status, "date",
"date" - lag("date") over (partition by ja_id order by "date") as days
from application;
I thought this would be a very simple query but for some reason, I can't seem to get the results I'm looking for. I have a table that has this structure. I just want a single entry for each account while summing the charges. I don't really care which date I keep, just one of them.
Account Charges Charges2 Date
1 100 50 1/1/2015
1 50 0 1/2/2015
2 50 0 2/4/2015
2 70 30 2/19/2015
3 100 0 1/12/2014
4 0 20 4/3/2015
4 40 20 4/9/2015
The result I want is:
Account Charges Charges2 Date
1 150 50 1/1/2015
2 120 30 2/4/2015
3 100 0 1/12/2014
4 40 40 4/3/2015
The result I currently get is:
Account Charges Charges2 Date
1 100 50 1/1/2015
2 70 30 2/19/2015
3 100 0 1/12/2014
4 40 40 4/9/2015
I thought this would be very simple and I tried below. But this doesn't sum them up, it just seems to return the rows where Charges2 is NOT 0.
SELECT Account, SUM(Charges) As TotCharges, SUM(Charges2) AS TotCharges2
FROM TABLE
GROUP BY Account
ORDER BY Account
You can apply the min() aggregate function to the date to limit the number of rows returned to one per account:
SELECT
Account,
SUM(Charges) AS TotCharges,
SUM(Charges2) AS TotCharges2,
MIN(Date) AS Date
FROM TABLE
GROUP BY Account
ORDER BY Account
Sample SQL Fiddle