SQL Server Query Explanation - sql

I am working on code from a person who held my position 2+ years ago, and am having trouble deciphering a block of their SQL code.
WHERE ACCOUNT NOT IN (SELECT ACCOUNT
FROM MWAPPTS A1
WHERE A1.ACCOUNT = A.ACCOUNT
AND ADATE > dbo.Endofmonth(ACTIONDATE)
AND REASON IN ('CPE','NPPE')
AND USERFLAG IN ( 'U', 'B' ))
dbo.Endofmonth is a stored procedure which gets the last day of the month for the inputed date.
If I am reading that right, we are not including rows where the account would be returned by the select statement shown. I am having problems with the select statement though. Am I correct that it is getting ACCOUNT where ADATE is older than the end of the month. The reason IS "CPE" or "NPPE", and the USERFLAG is either "U", or "B"?

Yes, you are returning the records where the account does not have the following:
1) an ADATE greater than the date returned by the function dbo.Endofmonth(ACTIONDATE).
2) a Reason that is CPE or NPPE
3) and the Userflag is either U or B.
You would have to look at the code in the function dbo.Endofmonth(ACTIONDATE) to determine exactly what it is returning.

Am I correct that it is getting ACCOUNT where ADATE is older than the end of the month.
The inner SELECT itself is looking for entries where ADATE is after the end of the month from ACTIONDATE. The NOT IN in the outer SELECTshould then retrieve rows where the account's ADATE is <= the end of the month from ACTIONDATE.
Your other assumptions seem correct.
Aside: It seems dbo.Endofmonth is a User-Defined Function, not a stored procedure (or it wouldn't be possible to call it like that).

Related

SQL filtering activity after certain event

I am struggling with a SQL query.
My query looks something like this:
Select
Count(user-id),
sum(distinct(date),
Sum(characters-posted)
From (
Select
Date,
User-Id,
Session-Id,
Characters—posted,
Variant-id
From database-name
Where date between ‘2022-09-01’ and ‘2022-09-31’)
This works ok. But, there is another field in the table “mailing-list”, which is just 0 or 1. I want to only get activity for members from the date when they join the mailing list onwards, even if they then leave the list, so can’t just do “where mailing-list=1”.
How can I do this?
It's not obvious what works fine for you as it seems to be uncommon to sum dates, given it is a regular date format. Are you trying to get number of active dates? as for the bottom question you might.
As for your buttom line quesiton, it seems that you might want to use a cte or subselect in a join.
your query...
from db_name dbn
inner join (select user_id, min(date) date from database_name
where mailing_list = 1 group by 1) start_date
on start_date.user_id = dbn.user_id
and start_date.date <= dbn.date
That way you're only getting activity starting from the first time your users join the mailing list.
But I still think you have an error in your final query, check it out.

Executing a Aggregate function within a case without Group by

I am trying to assign a specific code to a client based on the number of gifts that they have given in the past 6 months using a CASE. I am unable to use WITH (screenshot) due to the limitations of the software that I am creating the query in. It only allows for select functions. I am unsure how to get a distinct count from another table (transaction data) and use that as parameters in the CASE I have currently built (based on my client information table). Does anyone know of any workarounds for this? I am unable to GROUP BY clientID at the end of my query because not all of my columns are aggregate, and I only need to GROUP BY clientID for this particular WHEN statement in the CASE. I have looked into the OVER() clause, but I am needing my date range that I am evaluating to be dynamic (counting transactions over the last six months), and the amount of rows that I would be including is variable, as the transaction count month to month varies. Also, the software that I am building this in does not recognize the PARTITIONED BY parameter of the over clause.
Any help would be great!
EDIT:
it is not letting me attach an image... -____- I have added the two sections of code that I am looking for assistance with!
WITH "6MonthGIftCount" (
"ConstituentID"
,"GiftCount"
)
AS (
SELECT COUNT(DISTINCT "GiftView"."GiftID" FROM "GiftView" WHERE MONTHS_BETWEEN("GiftView"."GiftDate", getdate()) <= 6 GROUP BY "GiftView"."ConstituentID")
SELECT...CASE
WHEN "6MonthGiftCount"."GiftCount" >= 4
THEN 'A010'
)
Perform your grouping/COUNT(1) in a subquery to obtain the total # of donations by ConstituentID, then JOIN this total into your main query that uses this new column to perform its CASE statement.
select
hist.*,
case when timesDonated > 5 then 'gracious donor'
when timesDonated > 3 then 'repeated donor'
when timesDonated >= 1 then 'donor'
else null end as donorCode
from gifthistory hist
left join ( /* your grouping subquery here, pretending to be a new table */
select
personID,
count(1) as timesDonated
from gifthistory i
WHERE abs(months_between(giftDate, sysdate)) <= 6
group by personid ) grp on hist.personid = grp.personID
order by 1;
*Naturally, syntax changes will vary by DB; you didn't specify which it was based on, but you should be able to use this template with whichever you utilize. This works in both Oracle and SQL Server after tweaking the month calculation appropriately.

how do i get my customer records to still appear in the table beyond the 5 days advance period

I have a query that pull out all customers records I will need to call within the next 5 days in the where clause as:
Remind to call =< DATEADD(DD,5,GETDATE() and
Remind to call >= GETDATE()
The way i want it to work is that i want all customers records that i need to call 5 days in advance from GETDATE(). Once it has entered the table, it needs to stay in the table until users enters a date for the 'Confirmstart' field on web application.
What happens is my query displays the data as it should except it removes the customers record after the 5 days where i want the records to remain until the user has entered a date for the 'ConfirmStart' field
For example - Lets say todays date is 03/08/2016 where I want to pull out the customers i need to call within the next 5 days, therefore in my where clause i wrote:
<Remind to call =< DATEADD(DD,5,GETDATE() and
<Remind to call >= GETDATE()
The Dateadd should pull out records up to 08/08/2016. t also say record iD called 'CR1' that has a RemindToCall date 08/08/2013 meet this criteria.
The 'CR1' record appears in the table which is great. However when GETDATE() reaches the 9/08/2016, the 'CR1' record disappears from the table when i want it to still remain in that table until the 'ConfirmedStart' date is entered.
How do i get my customer records to still appear in the table beyond the 5 days advance period even though i need the records to appear 5 days in advance?
Further Information:
To elaborate on my above example - here is the SQL code that for the 'CR1' record but instead of it being named 'CR1' in this live example its CoS ID record called'1232' - everything else remains the same:
SELECT
CoSID,
SurName,
FirstName,
EmailAddress,
CONVERT (varchar,UKAddressDeadline,103) as UKAddressDeadline,
CONVERT (varchar,PlacementStart,103) as PlacementStart,
CONVERT (varchar,PlacementEnd,103) as PlacementEnd,
CONVERT (varchar,RemindToCall,103) as RemindToCall,
ExtReference,
HostOrgName,
UKEndorsement,
PaymentUKBA
FROM
dbo.tbl_CoS
WHERE
RemindToCall between CAST('2016-08-03' AS DATE) and DateAdd(DD,+5, CAST('2016-08-03' AS DATE)) AND
(CoSNotRequired is null and
AppWithdrawn = 0 and
CoSWithdrawn = 0 and
VisaRejected = 0 and
UKAddressDeadline is not null AND
ConfirmedStart is NULL OR
UKEndorsement is NULL)
SQL RESULT of above
I hope this extra information/details help you.
Thanks people :D
assuming that the Confirmstart is null when no value are entered.
Add that to your where clause
WHERE
(
(
[Remind to call] =< DATEADD(DD,5,GETDATE() and
[Remind to call] >= GETDATE()
)
OR
(
Confirmstart IS NULL
)
)
Maybe you need something like this:
([Remind to call] =< DATEADD(DD,5,GETDATE() and
[Remind to call] > CONVERT(varchar(8), GETDATE(), 112)) or
ConfirmStart is Null
In other words, you have to pass in the second line not GetDate(), but 08/08/2016 00:00:00

Report Next Date in Sequence

Our database keeps track of only 5 billing payments received each month. How can I write a select statement that will look, sequentially, at each payment received date and if there is a date entered to move on the the next payment, etc...then eventually come across the date with an empty field and report that date?
I've tried the following case statement but think I am on the wrong track;
select db.identifier,
case when recdate1 is not null then recdate1
when recdate2 is not null then recdate2
when recdate3 is not null then recdate3 end
from db
You should use the COALESCE function for this. The COALESCE function will take n number of input fields, and return the first NOT NULL input field from left to right. In other words, if you sequence the recdate fields from recdate1 to recdate 5, it will return the first one that is NOT NULL.
Here is the code to achieve this.
SELECT db.identifier
, COALESCE(recdate1, recdate2, recdate3, recdate4, recdate5) AS recdate
FROM mytable
Here is a link to the COALESCE function for more information. Hope this helps.
https://msdn.microsoft.com/en-us/library/ms190349.aspx

SQL figuring out days remaining based on days interval (using SQL Server 2005)?

I have a table that represents a user's subscription to our system. I have two tables. One represents the subscription for an account and the other represents the type of subscription. The subscription table relates to the subscription type table with a subscriptionTypeID field in the subscription types table. I need to figure out the days remaining for that account. Here is my example:
The user signed up on January 1, 2010 and their term is 30 days. Based on today's date (January 25, 2010) they would have 6 days remaining.
I need help designing the SQL. Here is what I have so far in my stored procedure:
#SubscriptionTypesID int
Declare #term int
Declare remainder int
Set #term = (SELECT subscriptionTerm
FROM dbo.SubscriptionTypes
where dbo.SubscriptionTypes.SubscriptionTypesID = #SubscriptionTypesID)
Now i need to figure out what to do with the remainder query, or if I can somehow have one SQL statement so I don't have to get the term separately.
Update:
Here is what I got now with all your help, but I still want a more elgant way to pump the term field value into the query:
Select (DateDiff(day,getDate(),DATEADD (day , 30, '01/01/2010' ))) days
Update 2.0 ;)
Sometimes the answer is right in front of me and I can't even see it. I tend to over think problems and make them more complicated than they need to be. Thanks to everyone who helped! HEre is the code:
SELECT (DateDiff(day,getDate(),DATEADD (day , subscriptionTerm, dbo.Subscriptions.subscriptionDate ))) days
FROM
dbo.Subscriptions
INNER JOIN dbo.SubscriptionTypes ON (dbo.Subscriptions.subscriptionTypeID = dbo.SubscriptionTypes.SubscriptionTypesID)
WHERE
dbo.Subscriptions.userID = 129
You can use Datadiff functionality from sql:
http://msdn.microsoft.com/en-us/library/ms189794.aspx
You could also solve it using:
DATEADD (datepart , number, date )
You can find more in the same MSDN page, just use the searchbox and type "Dateadd"
Good luck with your remaining time thingie ;)
Err, why don't you just compare the current date to the subscription date +30 days? I believe that would look like
if(GETDATE() > DATEADD(day,30,#SubscriptionDate))
BEGIN
END
In the comments below you asked how to get teh number of days. SQL has a method for that...
SELECT DATEDIFF(datepart,start,end)
To get the value and use it in different places you can use the following syntax:
DECLARE #Difference int
SELECT #Difference = DATEDIFF(day,#SubscriptionDate,GETDATE())
HEre it is...Thanks all for the insight:
SELECT (DateDiff(day,getDate(),DATEADD (day , subscriptionTerm, dbo.Subscriptions.subscriptionDate ))) days
FROM
dbo.Subscriptions
INNER JOIN dbo.SubscriptionTypes ON (dbo.Subscriptions.subscriptionTypeID = dbo.SubscriptionTypes.SubscriptionTypesID)
WHERE
dbo.Subscriptions.userID = 129