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.
Related
I have a Login Table like this:
Date,UserID
2020-08-01,1
2020-09-01,1
2020-09-07,2
2020-10-01,3
2020-10-12,4
2020-10-25,1
Basically, every time a user logins to my application, it register the date and the userID. I need to know the number of active users. To me an active user is one that has login in the previous thirty days of every day in the last week. For instance, let's say we are counting this week which goes from 2020-10-09 (October 9 2020) to 2020-10-15 (October 15 2020). Then I would go like this:
Check UserID = 1:
Has user login anytime between ('2020-10-09' - 30) and '2020-10-09'
Has user login anytime between ('2020-10-10' - 30) and '2020-10-10'
And so on until 2020-10-15
Then, it goes the same for each user ID.
In other words, I check the number of users that have login in a sliding Window of 30 days during a week. I hope this makes sense.
This is what I had in mind:
DROP TABLE IF EXISTS #ActiveUsers
CREATE TABLE #ActiveUsers (UserID bigint)
DECLARE #lowerDate Datetime='2020-10-09'
DECLARE #upperDate Datetime='2020-10-15'
DECLARE #activeSpan int=30
WHILE(#lowerDate <= #upperDate)
BEGIN
SELECT e.UserID INTO #ActiveUsers FROM
(SELECT DISTINCT(UserID) FROM logins WHERE Date >= (#lowerDate - #activeSpan)) AS e
WHERE e.UserID NOT IN (SELECT UserID FROM #ActiveUsers)
SET #lowerDate = #lowerDate + 1
END
PRINT SELECT COUNT(*) FROM #ActiveUsers
My reasoning was like this:
Check unique UserIDs in the timeframe.
Insert the unique ones in the temporary table as ling as they have not been previously inserted
Count the total after looping through the selected dates.
But besides being quiet inelegant I have not been able to make it work.
I would appraciate any advice.
Thank you!
I'm not sure if I understand the requirement - but let me confirm my understanding
Let's assume your 'upperDate' is 7 October. That means you would like to check that a user had done all of the following
Had logged in between 1 Sep and 1 October
Had logged in betweem 2 Sep and 2 October
...
Had logged in between 7 Sep and 7 October
Now, imagine three users, all who had logged in only once
The first logged in on 20 September
The second logged in on 3 September
The third logged in on 3 October
Their results would be as follows
The first would count as active as they were identified by all 7 tests.
The second would not count as active as they fail the tests from '4 Sep to 4 Oct' and later.
The third would not count as active as they fail the tests from '1 Sep to 1 Oct' and '2 Sep to 2 Oct'.
In other words - I think all you need to do is find the logins between your upperdate minus 30 days, to upperdate minus 7 days.
As such you wouldn't need a loop - the easiest check is
DECLARE #upperDate Datetime = '20201015';
DECLARE #activeSpan int = 30;
SELECT DISTINCT(UserID)
FROM logins
WHERE [Date] >= DATEADD(day, - #activeSpan, #upperDate)
AND [Date] <= DATEADD(day, -7, #upperDate);
I am trying to create a report for labour effectiveness in a manufacturing business that links to 2 x distinct MS SQL databases.
"Database A" contains information about what employees were doing when they were on shift.
"Database B" contains information about what time an employee clocked in or out for payroll info.
One of the comparisons I want to report on, is the total time an employee was logged into a job vs the total time they were clocked in the building. The data is related on employee number. The main report is linked to database A and is grouped on "Employee Name", within the group footer, there is a sub report linked to Database B and the employee name is passed through as a parameter.
My problem is the way database B records clocking in. I am using a SQL command to collect the data:
SELECT
tws.date_and_time
, CONVERT(date, tws.date_and_time) AS 'Date'
,te.first_name
, te.last_name
, concat(te.first_name,' ', te.last_name) AS 'ConcatName'
, CASE WHEN tws.flag IN (1,3) THEN 1 ELSE 0 END as manual_adjustment
, ROW_NUMBER() OVER (PARTITION BY tw.date_and_time ORDER BY tws.date_and_time ASC) AS swipe_number
, ROW_NUMBER() OVER (PARTITION BY tw.date_and_time ORDER BY tws.date_and_time ASC) % 2 AS in_swipe
FROM temployee te
INNER JOIN twork tw
ON te.employee_id = tw.employee_id AND tw.type = 1000
INNER JOIN twork_swipe tws
on tw.work_id = tws.work_id
The "swipe_number" details what number swipe that record is in the time period (e.g. 1st, 2nd, 3rd etc.)
The "in_swipe" displays 1 if this is the employee clocking in or 0 if it employee clocking out.
I am grouping the sub report on date.
This is relatively straight forward if an employee clocks in and out once on the same day, but I am struggling to work out how to account for if an employee clocks in and out multiple times during a shift (for a break for example) or if an employee clocks in on one day and out on another (night shift for example).
I need to sum the total time an employee is clocked in, so I need to evaluate if the 1st clock of the day is an "in swipe", (swipe_number = 1 AND in_swipe = 1) if it is not, it should not be recorded as the difference between swipe_number 2 and 1, it should be from the start of the day (00:00:0000) to swipe_number = 1 as this indicates the employee has been there since midnight.
Likewise if the last (or only) "swipe_number" of the day is an "in swipe", the time should be recorded as between that time and 23:59:5999.
Outside of this, I need to find the time between the date time fields where swipe numbers = 2 & 1, 4 & 3, 6 & 5 etc. (no fixed number of times a swipe can occur).
Can this be handled dynamically in formulas?
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)
Hi im looking to compare several rows and check if a certain condition is true/false.
The tables has several columns the ones im interested in are:
Events.Badgeno
Events.Name
Events.Date
Events.Time
Events.Region_id
Events.Data
The region ID can either be 1 or 2.
I want to check weather the same badgeno registers with a different region within a specified date/time difference say 10 mins. (Could be 10 mins before or 10 mins after).
I'm looking to show the records which don't have a record against the 2 regions.
As a further note it should only be within the first and last records of that badge per day.
Normally each record should have a region 1 and 2 record at the start and end. But there maybe multiple region 1's through out the day.
Any suggestions for the best method?
Id Date Time Name Badgeid Region
3385033 27/02/2014 08:16:11 FirstName Surname 5304 2
I think something like this would work
SELECT e.Badgeno,e.Name, e.Date, e.Time,e.Region_id, e.Data
FROM events e
INNER JOIN events e1 ON e1.BadgeNo = e.BadgeNo AND e1.Region_id <> e.RegionId AND DATEDIFF(minutes,e1.date + e1.time,e.date + e.time) > -10 AND DATEDIFF(minutes,e1.date + e1.time,e.date + e.time) < 10
WHERE e1.Region_id IS NULL
you should provide sample data.
This Query is not complete,you can try something with
row_number/rank/dense, partition and check thus number column
generated .
select *,
row_number()over(partition by badgeno,regionno order by badge no)rn from table
where condition of date time
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
)