I have an SQL table named "accounts" with the following columns:
registration_date
account_id
and have another SQL table named "revenue" with the following columns:
account_id
revenue_month
sales_revenue
What I am trying to achieve is to get the following:
Get a count of customers that registered between Jan and Dec 2017, and a count of how many of them bought something in 2017 (ie. sales_revenue more than 0).
I am very new to SQL and I tried the following but I couldn't do it.
SELECT COUNT account_id
FROM accounts
WHERE registration_date BETWEEN #01/01/2017# AND #12/31/2017#;
should give me the number of accounts that were registered in 2017?
and then
SELECT COUNT account_id
FROM revenue
WHERE sales_revenue > 0;
should give me the number of accounts that had a revenue of more than 0?
What am I missing? I would appreciate any help.
THANKS!
Try this out:
select count(account_id) as total,
sum(case when sales_revenue > 0 then 1 else 0 end) as sales_rev
FROM accounts
WHERE registration_date BETWEEN #01/01/2017# AND #12/31/2017#;
Let me know in case of any queries.
SELECT
COUNT(DISTINCT accounts.account_id)
FROM
accounts, revenue
WHERE
accounts.registration_date BETWEEN #01/01/2017# AND #12/31/2017#
AND
revenue.revenue_month BETWEEN #01/2017# AND #12/2017#
AND
accounts.account_id = revenue.account_id
AND
sales_revenue > 0
Oracle (again). Your database might use different functions.
Presuming that REGISTRATION_DATE is of a DATE datatype (and yes, it should be), then this might do the job:
select count(*)
from accounts
where extract(year from registration_date) = 2017;
The same goes for revenue - presuming that REVENUE_MONTH is DATE. If it is not, what is it?
select count(distinct account_id)
from revenue
where extract(year from revenue_month) = 2017
having sum(sales_revenue) > 0;
Try the following
Get a count of customers that registered between Jan and Dec 2017
SELECT COUNT (account_id)
FROM accounts
WHERE registration_date BETWEEN '01-JAN-2017' AND '12-DEC-2017'
and a count of how many of them bought something in 2017 (ie. sales_revenue more than 0).
SELECT COUNT (account_id)
FROM revenue
WHERE sales_revenue > 0
AND registration_date BETWEEN '01-JAN-2017' AND '12-DEC-2017'
The above is Oracle, your database would be something similar.
If you post a SQLFiddle, sample data and expected results, you'll get better answers...
You are missing a join.
Table accounts tells you who registered in the date range you care about, and table revenue tells you what they bought.
Not every account bought something, so you need an outer join.
As you only want to count the number of accounts that bought something, rather than the number of transactions, you have to use a distinct count. Not supported on every platform.
You want something like:
SELECT COUNT (a.*), count(distinct r.account_id)
FROM accounts a
outer join revenue r
on a.account_id = r.account_id
WHERE a.registration_date BETWEEN #01/01/2017# AND #12/31/2017#
and r.revenue_Month between '01/2017' and '12/2017'
This gives you all customers who registered in 2017 along with the information whether they bought something in 2017:
select
account_id,
case when exists
(
select *
from revenue r
where r.account_id = a.account_id
and r.sales_revenue > 0
and r.revenue_month like '%2017%'
) then 1 else 0 end as has_bought_in_2017
from accounts a
where year(registration_date) = 2017;
(You may want to change the LIKE clause; I don't know how your revenue_month is built.)
Now use this query to get the counts:
select
count(*) as registered_in_2017,
sum(has_bought_in_2017) as and_have_bought_in_2017
from (<above query>) q;
SELECT COUNT(account_id)
FROM accounts
WHERE registration_date BETWEEN '01/01/2017' AND '12/31/2017';
This will give you the count of account id who has registered in between 01/01/2017 AND 12/31/2017
SELECT COUNT(account_id)
FROM revenue
WHERE sales_revenue > 0;
This will give you the number of account id's who has sales_revenue greater than zero.
If you want the number of accounts between 01/01/2017 AND 12/31/2017 and
sales_revenue > 0 then:
select count(account_id)
from accounts a,revenue r
where a.registration_date BETWEEN '01/01/2017' AND '12/31/2017'
and r.sales_revenue > 0;
Related
Right now I have a query that lets me know which users didn't make a purchase 12 months prior to becoming members. These users have MEM_PRE_12=0 and I want to filter off those users more natively using SQL partitions rather than always putting rudimentary WHERE criteria.
Here is the SQL I use to find the users I want/don't want.
SELECT SUM(CASE WHEN DATE <= DATEADD(month, -12, U.INSERTED_AT) THEN 1 ELSE 0 END) AS MEM_PRE_12, I.CLIENTID, I.INSTALLATIONID
FROM <<<My_Joined_Tables>>>
GROUP BY I.CLIENTID, I.INSTALLATIONID
HAVING MEM_PRE_12 != 0
ORDER BY MEM_PRE_12
After this I'm going to have to go back and say where I.CLIENTID in the above nested query and select the actual information I want from users who made purchases greater than their insertion date.
How can I do this without so much nesting of all these joined tables?
If you want the detailed rows for customers who made a purchase in the last 12 months, you can use window functions:
with q as (
<whatever your query logic is>
)
select q.*
from (select q.*,
SUM(CASE WHEN DATE <= DATEADD(month, -12, U.INSERTED_AT) THEN 1 ELSE 0 END) over (partition by CLIENTID, INSTALLATIONID) as AS MEM_PRE_12
from q
) q
where mem_pre_12 > 0;
I have this table called table a
I need to get the CustomerID, sum(Income) of 2015, sum(Income) of 2016, did he ever bought productId A (boolean), is the total sum(income)> 1000 (boolean), number of total InvoiceID
all that in one query and the results should be with 1 row per customer.
please help I don't even know how to start!
This is basically conditional aggregation:
select customerid,
sum(case when extract(year from date) = 2015 then sales end) as sales_2015,
sum(case when extract(year from date) = 2016 then sales end) as sales_2016,
max( product = 'A' ) as ever_bought_a,
sum(income) > 1000 as sum_exceeds_1000,
count(*) as num_invoices
from t
group by customerid;
You haven't specified a database, so this is really psuedocode. You'll need to adapt it for your particular database.
There are 2 tables - Products and Sales
Products
prod_id
prod_nm
Sales
prod_id
cust_id
sls_dt
sls_amt
Write a query selecting ALL the products. For each product show total of sales amounts in the past 30 days or 0 if not sold in 30 day withoug using subqueries.
Since different RDBMS have different date functions, you can filter by date using the following pseudo code - sls_dt > now() - 30.
Im new to sql and im trying it like this as i found this online.
Select prod_id, prod_nm from(
Select sls_amt
From Sales) as t
Where t.rank = 1
However, this isnt' working. Any help is appreciated
Try below:
select p.prod_id,
p.prod_nm,
sum(s.sls_amt)
from products p
left outer join Sales s on p.prod_id = s.prod_id
and s.sls_dt > now() - 30
group by p.prod_id,
p.prod_nm;
I have a table which has account information for each individual working day. Each record shows the balance on the account for that particular day. I need to create a field that has a running count on how many days it has been since the balance on that particular account was zero.
For example: I have an account which is number 00000001. It was opened a week ago. The database has created a record for the account for last Tuesday, Wednesday, Thursday, Friday and Monday. The account did not have a balance until Friday and the balance was the same for Monday. I want the field to show '2' as a result. Further to this if the balance drops to '0' today, I need the count to reset on the next record and start again if the account has a balance the following day. There are several accounts in this table so I need this to work for each one individually.
Below is as far as I have got:
SELECT
pos.EffDate,
cus.CNA1,
pos.ACNO,
pos.CCY,
pos.LDBL,
pos.LDBLUSD,
MIN(pos3.effdate) AS 'First Post Date',
pos3.Balcount
FROM[dbo].[Account] AS pos
JOIN [dbo].[Customer] AS cus ON ((pos.CNUM=cus.CUST_NO) AND (cus.effdate=pos.effdate))
LEFT JOIN (SELECT pos2.effdate, pos2.ACNO, SUM(CASE pos2.LDBL WHEN 0 THEN 0 ELSE 1 END) AS 'Balcount' FROM [dbo].[Account] AS pos2 GROUP BY pos2.ACNO, pos2.Effdate HAVING pos2.effdate BETWEEN pos2.effdate AND MIN(pos2.effdate)) pos3 ON pos3.ACNO = pos.ACNO
WHERE pos.effdate >='1 Dec 2015' AND pos.Effdate <'30 Dec 2015'
AND pos.srcsys = 'MP_UK'
AND pos.LDBL <= 0
AND pos.CNUM <> '000020'
AND pos.intbear <> 'N'
AND pos.blockdeb IS null
GROUP BY pos.EffDate,cus.CNA1,pos.ACNO,pos.CCY,pos.LDBL,pos.LDBLUSD, pos3.Balcount
ORDER BY 1,2,3
If you need me to clarify anything please let me know. All help is greatly appreciated.
Thanks,
Ben
Basically, you want to group the data, based on the number of time the account is zero before a given row. Then, within each group, you want to enumerate the records.
In SQL Server 2012+, you can do these things with window functions. I am not sure exactly what your sample query has to do with the question, but here is the basic idea:
select a.*, row_number() over (partition by cust_no, grp order by eff_date) as seqnum
from (select a.*,
sum(case when balance = 0 then 1 else 0 end) over
(partition by cust_no order by eff_date) as grp
from Account a
) a;
In earlier versions of SQL Server, you can do something very similar using apply.
I want to count the number of transactions for the first 30 days from an account's creation for all accounts. The issue is not all accounts were created at the same time.
Example: [Acct_createdTable]
Acct Created_date
909099 01/02/2015
878787 02/03/2003
676767 09/03/2013
I can't Declare a datetime variable since it can only take one datetime.
and I can't do :
Select acctnumber,min,count(*)
from transaction_table
where transactiondate between (
select Created_date from Acct_createdTable where Acct = 909099)
and (
select Created_date from Acct_createdTable where Acct = 909099)+30
Since then it'll only count the number of transaction for only one acct.
What I want for my output is.
Acct First_30_days_count
909099 23
878787 190
676767 23
I think what you're looking for is a basic GROUP BY query.
SELECT
ac.acctnumber,
COUNT(td.id)
FROM Acct_createdTable ac
LEFT JOIN transactiondate td ON
td.acct = ac.acctnumber
AND
td.transaction_date BETWEEN ac.create_date AND DATEADD(30, DAY, ac.create_date)
GROUP BY
ac.acctnumber
This should return number of transactions within first 30 days for each account. This of course is pseudocode as you didn't state your database platform. The left join will ensure that accounts with no transactions in that period will get displayed.
An alternative solution would be to use outer apply like this:
select a.acct, o.First_30_days_count
from acct_createdtable a
outer apply (
select count(*) First_30_days_count
from transaction_table
where acctnumber = a.acct
and transactiondate between a.created_date and dateadd(day, 30, a.created_date)
) o;