Getting Expired Purchases And Associated Features - sql-server

I am updating our in-house purchase system. While doing this, I had to move the service expiration date from the client table to the purchase table so each system could expire separately. I am trying to update the SQL statement to get systems that need to be billed, but am running into issues. Below is a simplified example of what I need:
Purchase Table
ID Product ClientID SystemID IsSystem ExpireDate
1 System1 12 1 1 9/22/2015
2 Feature1 12 1 0 NULL
3 Feature2 12 1 0 9/22/2016
4 System2 12 2 1 9/22/2016
5 Feature1 12 2 0 9/22/2015
6 Feature2 12 2 0 NULL
In the example above, I would need to get lines 1, 2 and 3. What I need to do is:
Look at each system to see if the ExpireDate is less than or equal to a given date (say today)
If it is, take all rows with a matching ClientID and SystemID reguardless of ExpireDate
Although line 5 would be expired, it would not get included because the system it is a part of has not expired.
This is getting inserted into a much larger SQL statement spanning several tables, but I should be able to extrapolate from an example with this table.

This is probably best accomplished using a common table expression that gets the expired client and systemIDs and then checks every row in your table against that list:
WITH expired AS
(
SELECT DISTINCT
ClientID,
SystemID
FROM purchase
WHERE
CONVERT(DATE, ExpireDate) <= CONVERT(DATE, GETDATE())
AND isSystem = 1
)
SELECT
*
FROM purchase p
WHERE
EXISTS (SELECT * FROM expired WHERE p.ClientId = ClientID AND p.SystemId = SystemId)

Related

In SQL Server, how do I get the date of an event from a table and the date the previous event happened?

I'm using Microsoft SQL Server 2016 (SP2) (13.0.5026.0 (X64). I have a query that joins a people table with a contacts table. The people table has the client detail and the contacts table tells us the last time that client has made a contact.
The below query links the tables and gives me the client ID and the date they made contact
SELECT
DP.dim_person_ID AS [Dim_Person_ID],
CAST(FC.CONTACT_DTTM AS date) AS [Contact Date]
FROM
Child_Social.Fact_Contacts FC
INNER JOIN
CHILD_SOCIAL.DIM_Person DP ON FC.dim_person_ID = DP.Dim_Person_ID
If they made multiple contacts they will return a row for each one and the output will look like this
Person_ID
Contact Date
1
01/01/2023
1
01/10/2022
1
01/07/2022
1
01/04/2022
1
01/01/2022
2
02/01/2023
2
02/10/2022
2
02/07/2022
2
02/04/2022
2
02/01/2022
What I'm trying to do is to add a column to the query that shows the previous contact date as well eg return an output like
Person ID
Contact Date
Previous Contact Date
1
01/10/2022
01/07/2022
1
01/07/2022
01/04/2022
2
02/10/2022
02/07/2022
2
02/07/2022
02/04/2022
I'm unsure how to create a join/sub query that will calculate a previous episode (rather than a most recent episode or a first episode, just the previous one).
Any help or guidance gratefully received

Extend row-level security to a bridging table

I am working on row level security in my database. I have two tables. Row based security is implemented on data_table and only returns rows that the user can see.
data_table:
data_id name role
-----------------------------
1 test USER
2 another ADMIN
3 yep USER
type_table:
type_id name
-----------------
1 this
2 is
3 a
4 type
EXECUTE AS USER = 'USER';
SELECT * FROM data_table;
returns rows 1 and 3 only. If you execute as ADMIN, all of the rows are returned. This is working properly in my database.
However, my issue is my bridging table.
data_type_table:
data_type_id data_id type_id
1 1 2
2 1 3
3 2 1
4 2 2
5 3 1
6 3 4
As of right now
EXECUTE AS USER = 'USER';
SELECT COUNT(data_type_id) FROM data_type_table;
returns 6 because it's looking at all 6 rows in the table. I'm trying to set it up in such a way that user USER will only see rows in data_type_table which are referencing rows where data_table.role = 'USER' (this means that the select count query would return 4). What would be the simplest way to implement something like this?
My data_table will more than likely contain hundreds of thousands of rows. Efficiency could become a problem here.

if data not exist on a particular date then how to select the date which is previous and very close to given date in sql server 2008 R2

I have a table which have the following fields
Sno StockDate PartNo Quantity Location
1 22.11.2013 011011011 100 Perungudi
2 24.12.2013 011201120 1000 Kottivakkam
3 1.1.2014 011011011 80 Perungudi
If i need to select datas on 1.1.2014 means i have to list the following datas
Sno StockDate PartNo Quantity Location
2 24.12.2013 011201120 1000 Kottivakkam
3 1.1.2014 011011011 80 Perungudi
that is the stock available on that day is as showed above. i want to know how to i write the select query

T-SQL Group by / Order by + SQL Server Reporting Service Parameters

select
Users.UserId
,Users.FirstName + ' ' + Users.LastName AS
,[Month]
,[Day]
,x.[Przych]
,x.[Wych]
,x.[Przych] + [Wych] as [Ogół]
from
(select
CaseActionHistory.UserId
,month(CaseActionHistory.DateAdded) AS [Month]
,day(CaseActionHistory.DateAdded) AS [Day]
,sum(case when CaseActionHistory.CaseActionDefinitionId in (14,15,16) then 1 else 0 end) AS [Przych]
,sum(case when CaseActionHistory.CaseActionDefinitionId in (20,21,22,23,26) then 1 else 0 end) AS [Wych]
from CaseActionHistory
where CaseActionHistory.CaseActionDefinitionId in (14,15,16,20,21,22,23,26)
group by month(CaseActionHistory.DateAdded),day(CaseActionHistory.DateAdded), CaseActionHistory.UserId
order by month(CaseActionHistory.DateAdded) DESC,day(CaseActionHistory.DateAdded) DESC
OFFSET 0 rows
) AS x
inner join Users on x.UserId = Users.UserId
I'm trying to run out something out of this. My problem is: the results of such query are displayed like this:
User Month Day X
User1 7 31 6
User2 7 31 7
User3 7 31 9
User1 7 30 8
User2 7 30 7
User3 7 30 8
User4 7 31 10
User5 7 31 20
User6 7 31 23
User4 7 30 5
User5 7 30 7
User6 7 30 65
So in fact few Users are grouped into small groups which are displayed first, then 2nd group, etc. so I suppose there's a problem either with group by or order by.
As an addition I'd like to ask a question concerning parameters in SQL Server. Out of code below I'd like to set up 3 parameters:
User
Month
Day
But my problem is that when I set up details of parameter and I run it some values are multiplied. Same user is multiplied few times, same month, same day etc. also report itself is not reacting on any kind of change within parameters.
The main idea of a report is to show the number of phone calls done by every employee, each day, every month and to be able to compare results with others.
Calls are splitted into: outgoing and incoming. After every phone call employee adds to system an information regarding what phone call it was and what they managed to do during this phone call.
So in fact we are working on 2 tables in this case:
CaseActionHistory and Users
So the plan was to show the number of phone calls (incoming, outgoing and sum of those) for every day for every person.
Since CaseActionHistory table consits only ID of User which done the action and I'd like to show the person's name (which is placed in Users table obviously).
The problem is that the report should show around 20 Users one by one, so for 31st of June 20 Users one by one, for 30th 20 Users one by one etc, but it shows like 5 Users for 31st, then same Users for 30th, then next 5 Users for 31st etc (link to image showing the situation below)
http://img801.imageshack.us/img801/2088/7blu.png
Columns are:
UserId (to be replaced with UserName) Day Month Incming Outgoing Sum
The rows on the bottom for 31st July should be on the top of the list but they are not.
Welcome to stack overflow. A few things:
If your data is 'multiplying' may you just do a 'distinct' in your main select statement and determine if it is not your dataset repeating?
How are you applying parameters? They should be predicates and have nothing to do with groupings except indirectly. You may limit a set by a parameter but it will not affect your grouping directly, generally speaking.
What do you want to group by? Year, Month, (detail)?
SSRS starts out with a data connection (Data Source). You then apply a Data Set which is a query or proc. Which you have a query. You can apply a predicate to the main dataset with a 'where User = #User' or 'where User in (#User)'. The parameter will automatically be created if you do this in your dataset first with the '#(something)' creating a text parameter of said name. You see the Built In Fields, Parameters, Images, Data Sources, DataSets in the 'Report Data' view which you will use constantly in SSRS creation with 'Business Intelligence Development Studio'.
So a simple example would be that you want to add a group for the Day to your '(Details)' row. If you create a 'Table' element from the 'Toolbox' it will only have a single row called Details. Fill it with your X value and user. In the 'Design' surface at the bottom you will see 'Row Groups'. Right click on your 'Details' row and choose add parent group. Group by 'Day' check 'Add Group Header'. You now have another row that will be grouping by Day. You can repeat this process on the newly created group for a group for 'Month' and so and so on.

Outputting Results from complicated database structure (SQL Server)

This will be a long question so I'll try and explain it as best as I can.
I've developed a simple reporting tool in which a number of results are stored and given a report id, these results were generated from a particular quote being used on the main system, with a huge list of these being stored in a quotes table. Here are the current batch:
REPORTS
REP_ID DESC QUOTE_ID
-----------------------------------
1 Test 1
2 Today 1
3 Last Week 2
RESULTS
RES_ID TITLE REFERENCE REP_ID
---------------------------------------------------
1 Equipment Toby 1
2 Inventory Carl 1
3 Stocks Guest 2
4 Portfolios Guest 3
QUOTE
QUOTE_ID QUOTE
------------------------------------
1 Booking a meeting room
2 Car Park Policy
3 New User Guide
So far, so good, a simple stored procedure was able to pull all the information necessary.
Now, the feature list has been upped to include categories and groups of the quotes. In the Reports table quote_id has been changed to group_id to link to the following tables.
REPORTS
- REPORT_ID
- DESC
- GROUP_ID
GROUP
- GROUP_ID
- GROUP
GROUP_CAT_JOIN
- GCJ_ID
- CAT_ID
- GROUP_ID
CATEGORIES
- CAT_ID
- CATEGORY
CAT_QUOTE_JOIN
- CQJ_ID
- CAT_ID
- QUOTE_ID
The idea of these changes is so that instead of running a report on a quote I should now write a report for a group where a group is a set of quotes for certain occasions. I should also be able to run a report on a category where a category is also a set of quotes for certain departments. The trick is that several categories can fall into one group.
To explain it further, the results table has a report_id that links to reports, reports has a group_id that links to groups, groups and categories are linked through a group_cat_join table, the same with categories and quotes through a cat_quote_join table.
In basic terms I should be able to pull all the results from either a group of quotes or a category of quotes. The query will aim to pull all the results from a certain report under either a certain category, a group or both. This puzzle has left me stumped for days now as inner joins don't appear to be working and I'm struggling to find other ways to solve the problem using SQL.
Can anyone here help me?
Here's some extra clarification.
I want to be able to return all the results within a category, but as of right now the solution below and the ones I've tried always output every solution within a description, which is not what I want.
Here's an example of the data I have in there at the moment
Results
RES_ID TITLE REFERENCE REP_ID
---------------------------------------------------
1 Equipment Toby 1
2 Inventory Carl 1
3 Stocks Guest 2
4 Portfolios Guest 3
Reports
REP_ID DESC GROUP_ID
-----------------------------------
1 Test 1
2 Today 1
3 Last Week 2
GROUP
GROUP_ID GROUP
---------------------------------
1 Standard
2 Target Week
GROUP_CAT_JOIN
GCJ_ID GROUP_ID CAT_ID
----------------------------------
1 1 1
2 1 2
3 2 3
CATEGORIES
CAT_ID CAT
-------------------------------
1 York Office
2 Glasgow Office
3 Aberdeen Office
CAT_QUOTE_JOIN
CQJ_ID CAT_ID QUOTE_ID
-----------------------------------
1 1 1
2 2 2
3 3 3
QUOTE
QUOTE_ID QUOTE
------------------------------------
1 Booking a meeting room
2 Car Park Policy
3 New User Guide
This is the test data I am using at the moment and to my knowledge it is similar to what will be run through once this is done. In all honesty I'm still trying to get my head around this structure.
The result I am looking for is if I choose to search by group I'll get everything within a group, if I choose everything inside a category I get everything just inside that category, and if I choose something from a category in a group I get everything inside that category. The problem at the moment is that whenever the group is referenced everything inside every category that's linked to the group is pulled.
The following will get the necessary rows from the results:
select
a.*
from
results a
inner join reports b on
a.rep_id = b.rep_id
and (-1 = #GroupID or
b.group_id = #GroupID)
and (-1 = #CatID or
b.cat_id = #CatID)
Note that I used -1 as the placeholder for all Groups and Categories. Obviously, use a value that makes sense to you. However, this way, you can specify a specific group_id or a specific cat_id and get the results that you want.
Additionally, if you want Group/Category/Quote details, you can always append more inner joins to get that info.
Also note that I added the Group_ID and Cat_ID conditions to the Reports table. This would be the SQL necessary if and only if you add a Cat_ID column to the Reports table. I know that your current table structure doesn't support this, but it needs to. Otherwise, as my grandfather used to say, "Boy, you can't get there from here." The issue here is that you want to limit reports by group and category, but reports only knows about group. Therefore, we need to tie something to the category from reports. Otherwise, it will never, ever, ever limit reports by category. The only thing that you can limit by both group and category is quotes. And that doesn't seem to be your requirement.
As an addendum: If you add cat_id to results instead of reports, the join condition should be:
and (-1 = #CatID or
a.cat_id = #CatID)
Is this what you are looking for?
SELECT a.*
FROM Results a
JOIN Reports b ON a.REP_Id = c.REP_Id
WHERE EXISTS (
SELECT * FROM CAT_QUOTE_JOIN c
WHERE c.QUOTE_ID = b.QUOTE_ID -- correlation to the outer query
AND c.CAT_ID = #CAT_ID -- parameterization
)
OR EXISTS (
-- note that subquery table aliases are not visible to other subqueries
-- so we can reuse the same letters
SELECT * FROM CAT_QUOTE_JOIN c, GROUP_CAT_JOIN d
WHERE c.CAT_ID = d.CAT_ID -- subquery join
AND c.QUOTE_ID = b.QUOTE_ID -- correlation to the outer query
AND d.GROUP_ID = #GROUP_ID -- parameterization
)

Resources