How to select rows if it only existed after a specific date? - sql

How do I select rows if the data exists after a specified date? For example, I want to find the revenue when the TIN wasn't in the database before 2017. And if the TIN was in the database before 2017, I don't want to pull the revenue in the previous years.
For example, this pulls all the revenue, and doesn't take into consideration whether or not there was data associated with the TIN prior.
SELECT [DateRevenueAccrued]
,[TIN]
,[Net Revenue]
FROM [CSTM].[reports].[IncomeNew]
WHERE DateRevenueAccrued > '1/1/2017'

Is this what you want?
SELECT [DateRevenueAccrued], [TIN], [Net Revenue]
FROM [CSTM].[reports].[IncomeNew] i
WHERE NOT EXISTS (SELECT 1
FROM [CSTM].[reports].[IncomeNew] i2
WHERE i2.TIN = i.TIN AND
DateRevenueAccrued < '2017-01-01'
);

I guess the below if the question is TIN
exists/not exists though this is row by row
SELECT REVENUE FROM TABLE
WHERE (DateRevenueAccrued <
'1/1/2017' AND TIN IS NULL )OR
(DateRevenueAccrued >=
'1/1/2017')

Related

In SQL how do I select the latest date that does not have a zero value in another column

I am trying to select the max date in a table that has a Booking Date and a Written Premium value for that date. I want the newest date that has Written Premium (not equal to Zero).
In the above table I want, or expect the 4th Row in my query (7/28/2021, 330000), but I get the first row
(8/20/21, 0)
This is the query I run:
SELECT
MAX(booking_date) AS [Max Booking Date]
FROM
DW.dbo.Table1
GROUP BY
booking_year
HAVING
SUM(written_premium) <> 0
AND booking_year = '2021'
I think this is summing all the written premium, not over the rows so I am just getting the max booking date. Maybe I need a PARTITION BY function or something? I am stuck on this and would appreciate any help on how to best do this.
Thanks,
Brian
I think there are multiple options, but one could be:
SELECT TOP 1 booking_date, written_premium
FROM DW.dbo.Table1
WHERE written_premium <> 0
ORDER BY booking_date DESC
If all you want is the date then there is no need of group by and a HAVING clause.
Set your conditions in the WHERE clause:
SELECT MAX(booking_date) AS [Max Booking Date]
FROM DW.dbo.Table1
WHERE booking_year = '2021' AND written_premium <> 0;
If you want both columns:
SELECT TOP 1 booking_date AS [Max Booking Date], written_premium
FROM DW.dbo.Table1
WHERE booking_year = '2021' AND written_premium <> 0
ORDER BY booking_date DESC;

how to query a table date against a series of dates on another table

I have two tables, INVOICES and INV_PRICES. I am trying to find the Invoice table's part price from the Inv_Prices based upon the Invoice_Dt on the Invoice table; if the Invoice_Dt is between (greater than, but less than) or greater than the max EFF_DT on the Inv_Prices, then return that part's price.
I have tired variations on the following code, but no luck. I either do not get all the parts or multiple records.
SELECT DISTINCT A.INVOICE_NBR, A.INVOICE_DT, A.PART_NO,
CASE WHEN TRUNC(A.INVOICE_DT) >= TRUNC(B.EFF_DT) THEN B.DLR_NET_PRC_AM
WHEN (TRUNC(A.INVOICE_DT)||ROWNUM >= TRUNC(B.EFF_DT)||ROWNUM) AND (TRUNC(B.EFF_DT)||ROWNUM <= TRUNC(A.INVOICE_DT)||ROWNUM) THEN B.DLR_NET_PRC_AM
/*MAX(B.EFF_DT) THEN B.DLR_NET_PRC_AM*/
ELSE 0
END AS PRICE
FROM INVOICES A,
INV_PRICES B
WHERE A.PART_NO = B.PART_NO
ORDER BY A.INVOICE_NBR
Can someone assist? I have a sample of each table if needed.
Doesn't it work to put the condition in the JOIN conditions? You can calculate the period when a price is valid using LEAD():
SELECT i.INVOICE_NBR, i.INVOICE_DT, i.PART_NO,
COALESCE(ip.DLR_NET_PRC_AM, 0) as price
FROM INVOICES i LEFT JOIN
(SELECT ip.*, LEAD(eff_dt) OVER (PARTITION BY PART_NO ORDER BY eff_dt) as next_eff_dt
FROM INV_PRICES ip
) ip
ON i.PART_NO = ip.PART_NO AND
i.invoice_dt >= ip.eff_dt AND
(i.invoice_dt < ip.next_eff_dt or ip.next_eff_dt is null)
ORDER BY i.INVOICE_NBR

How to search for count of customers in SQL database?

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;

SQL count records depending on criteria

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.

Count number of transactions for first 30 days of account creation for all accounts

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;