Link data from sql from 2/3 columns - sql

I don't know if the question title is so clear, but here is my question:
I had table UsersMovements which contains Users along with their movements
UsersMovements:
ID
UserID
MovementID
Comments
Time/Date
I need help looking for a query which would give me if users 1, 2 & 3 had been in a common MovementID, knowing that I don't know what is the MovementID
The real case is that, I want to see if those X users which I would select been in an area (in a limited interval, assuming I had date/Time in the table)
Thank you

if you want to select list of movements which have userid 1,2 and 3 you can use group by with having
select movementid
from usermovements
where userid in(1,2,3)
group by movementid
having count(distinct userid)=3

Related

Finding entry count for each unique id in SQL

I have an SQL database that shows the amount of times a person submits an entry. I want to count how many time each person who owns a unique id makes a claim. Each unique i.d can make mulpile entries into the table and I want to find out how many everyone has made.
I also want to filter the people based on the amount of entries they have made. For example 10.
select id, entry, COUNT(ID) from Table where COUNT(entry) <=10 GROUP BY ID
This is my thinking so far but I havent had much success. If anyone could help I would greatly appreciate it.
This is all you need
select id, COUNT(*) cnt
from Table
GROUP BY ID
having COUNT(*) <= 10
order by 2 desc -- optional descending count
Optionally, add Order by 2. desc or asc

SQL count distinct values for records but filter some dups

I have a MS SQL 2008 table of survey responses and I need to produce some reports. The table is fairly basic, it has a autonumber key, a user ID for the person responding, a date, and then a bunch of fields for each individual question. Most of the questions are multiple choice and the data value in the response field is a short varchar text representation of that choice.
What I need to do is count the number of distinct responses for each choice option (ie. for question 1, 10 people answered A, 20 answered B, and so forth). That is not overly complex. However, the twist is that some people have taken the survey multiple times (so they would have the same User ID field). For these responses, I am only supposed to include the latest data in my report (based on the survey date field). What would be the best way to exclude the older survey records for those users that have multiple records?
Since you didn't give us your DB schema I've had to make some assumptions but you should be able to use row_number to identify the latest survey taken by a user.
with cte as
(
SELECT
Row_number() over (partition by userID, surveyID order by id desc) rn,
surveyID
FROM
User_survey
)
SELECT
a.answer_type,
Count(a.anwer) answercount
FROM
cte
INNER JOIN Answers a
ON cte.surveyID = a.surveyID
WHERE
cte.rn = 1
GROUP BY
a.answer_type
Maybe not the most efficient query, but what about:
select userid, max(survey_date) from my_table group by userid
then you can inner join on the same table to get additional data.

Simple SQL (hopefully!) Query Question

I hope someone can help me with my faltering steps to formulate a SQL query for the following problem.
I have a simple table that records visitor names and dates. The relationship is many to many, in that for any given date there are many visitors, and for any given visitor there will be one or more dates (i.e. repeat visits). There is a complicating third column that records the name of the exhibit(s) the visitor interacted with. The data might look like this:
NAME ART DATE
Joe Picture 1 23-1-09
Joe Picture 2 23-1-09
Joe Picture 3 23-1-09
Janet Picture 2 23-1-09
Joe Picture 2 31-2-09
I want to know what the distribution of single and multiple visits are, in other words, how many people only visited once, how many people visited on 2 separate days, how many on 3 separate days, and so on.
Can anyone help please? Thank you in anticipation!
Frankie
If you only want to count the total number of distinct visits, including multiple visits on the same date, you could use:
SELECT [Name],
COUNT(*) AS Count_Dates
FROM MyTable
GROUP BY [Name]
However, if you don't want to count multiple visits on the same date, you could use the following:
SELECT [Name],
COUNT(*) AS Count_Dates
FROM
(
SELECT DISTINCT [Name],
[Date]
FROM MyTable
) a
GROUP BY [Name]
This will show you the distribution of total people who visited x times per day. However, this will not display numbers for counts where 0 people visited that many times - for example, if nobody visited 8 times, then there won't be a row for Count_Dates = 8. If you did want to display a full list from 0-10 visits, you could create a temp table of Count_Dates and insert values from 0-10, then use it as part of the main query.
SELECT Count_Dates,
COUNT(*) AS Count_Visitors
FROM (SELECT [Name], COUNT(DISTINCT [Date]) AS Count_Dates FROM MyTable GROUP BY [Name]) a
GROUP BY Count_Dates
ORDER BY Count_Dates
SELECT NAME, COUNT(ART) as num_exhibits, COUNT(DATE) as num_days
FROM table GROUP BY NAME;
This will give you a table of each name along with the total number of visits for that name and the total number of dates visited.
To get an average exhibit per date you can do:
SELECT
NAME,
COUNT(ART) as num_exhibits,
COUNT(DATE) as num_days,
(num_exhibits / num_days) as avg_exhibit_per_day
FROM table GROUP BY NAME;

SQL Query to find if different values exist for a column

I have a temporary table with three columns
pay_id,
id_client_grp,
id_user
Basically i want to ensure that this table should have all the rows having same client group and same id_user if not i want to know which pay_id is the culprit and throw error to user.
Can somebody help me with a query.
Thanks,
Rishi
When you say 'culprit,' I assume you mean the pay_id(s) that are not like the others, assuming there is a majority.
The problem is all of the pay_id's could potentially become culprits once your SELECT COUNT(DISTINCT id_client_grp, id_user) returns > 1 record, if there is a relatively even distribution. It is difficult to program for this scenario, since you will need to determine what exactly a majority is.
Your best bet will be to return all distinct combinations of those 3 fields, then decide where to go from there based on your business logic.
So could this question be asked like this:
If I wanted to add a unique index on my table across the three columns: client group, id user, pay id, identify those that break the unique condition where we have non unique pay id for a client group and id user??
select a.id_client_grp, a.id_user, a.pay_id , a.count from (
/* this should return 1 row per client group and user, */
/* if the pay id is the same for all */
select id_client_grp, id_user, pay_id, count(1) as count
from table t
group by id_client_grp, id_user ) a
group by a.id_client_grp, a.id_user
/* if we have more than one row per client group and user, then we have a dupe, so report them all */
having count (1) > 1
If you want all the rows to have the same values for some set of columns (your question is not entirely clear to me as t9o what you want to be the same)
Do you know going in WHICH pay_id, id_client_grp all the rows should be? Or do you not care, as long as they are all the same?
If you know the values you are looking for, simply test for rows that are not set to those desired values
Select distinct id_user
From tempTable
Where pay_id <> #PayIdValue
Or id_client_grp <> #ClientGroupIDValue
If you don't care, and just want them all to be the same, and they're not, then you need to specify which of the more than one set of values IS the "culprit" as you said...
If you want some other question answered. please explain more clearly...
Based on yr comment, then, to determine if there is more than one id_client_grp, pay_id
Select Count(Distinct id_client_grp, pay_id)
From tempTable
If this = 1 then every record has the same values for these 2 fields.... Any other value indicates that three is more than one set of distinct values in the table.
SELECT DISTINCT p.pay_id,
t.[count]
FROM rishi_table p
INNER JOIN ( SELECT id_client_grp, id_user, COUNT(*) As 'count'
FROM rishi_table
GROUP BY id_client_grp, id_user
HAVING COUNT(*) > 1 ) t
ON p.id_client_grp = t.id_client_grp AND p.id_user = t.id_user
basically create a set with the dupes, and bounce that against the main table to get your offending list.
SELECT DISTINCT id_client_grp, id_user
should let you do something like
IF ##ROWCOUNT > 1 THEN
...
Or possibly SELECT COUNT(DISTINCT id_client_grp, id_user) ...
but that's more vendor-dependent as to its availability and proper syntax.

Compute Users average weight

I have two tables, Users and DoctorVisit
User
- UserID
- Name
DoctorsVisit
- UserID
- Weight
- Date
The doctorVisit table contains all the visits a particular user did to the doctor.
The user's weight is recorded per visit.
Query: Sum up all the Users weight, using the last doctor's visit's numbers. (then divide by number of users to get the average weight)
Note: some users may have not visited the doctor at all, while others may have visited many times.
I need the average weight of all users, but using the latest weight.
Update
I want the average weight across all users.
If I understand your question correctly, you should be able to get the average weight of all users based on their last visit from the following SQL statement. We use a subquery to get the last visit as a filter.
SELECT avg(uv.weight) FROM (SELECT weight FROM uservisit uv INNER JOIN
(SELECT userid, MAX(dateVisited) DateVisited FROM uservisit GROUP BY userid) us
ON us.UserID = uv.UserId and us.DateVisited = uv.DateVisited
I should point out that this does assume that there is a unique UserID that can be used to determine uniqueness. Also, if the DateVisited doesn't include a time but just a date, one patient who visits twice on the same day could skew the data.
This should get you the average weight per user if they have visited:
select user.name, temp.AvgWeight
from user left outer join (select userid, avg(weight)
from doctorsvisit
group by userid) temp
on user.userid = temp.userid
Write a query to select the most recent weight for each user (QueryA), and use that query as an inner select of a query to select the average (QueryB), e.g.,
SELECT AVG(weight) FROM (QueryA)
I think there's a mistake in your specs.
If you divide by all the users, your average will be too low. Each user that has no doctor visits will tend to drag the average towards zero. I don't believe that's what you want.
I'm too lazy to come up with an actual query, but it's going to be one of these things where you use a self join between the base table and a query with a group by that pulls out all the relevant Id, Visit Date pairs from the base table. The only thing you need the User table for is the Name.
We had a sample of the same problem in here a couple of weeks ago, I think. By the "same problem", I mean the problem where we want an attribute of the representative of a group, but where the attribute we want isn't included in the group by clause.
I think this will work, though I could be wrong:
Use an inner select to make sure you have the most recent visit, then use AVG. Your User table in this example is superfluous: since you have no weight data there and you don't care about user names, it doesn't do you any good to examine it.
SELECT AVG(dv.Weight)
FROM DoctorsVisit dv
WHERE dv.Date = (
SELECT MAX(Date)
FROM DoctorsVisit innerdv
WHERE innerdv.UserID = dv.UserID
)
If you're using SQL Server 2005 you don't need the sub query on the GROUP BY.
You can use the new ROW_NUMBER and PARTION BY functionality.
SELECT AVG(a.weight) FROM
(select
ROW_NUMBER() OVER(PARTITION BY dv.UserId ORDER BY Date desc) as ID,
dv.weight
from
DoctorsVisit dv) a
WHERE a.Id = 1
As someone else has mentioned though, this is the average weight across all the users who have VISITED the doctor. If you want the average weight across ALL of the users then anyone not visiting the doctor will give a misleading average.
Here's my stab at the solution:
select
avg(a.Weight) as AverageWeight
from
DoctorsVisit as a
innner join
(select
UserID,
max (Date) as LatestDate
from
DoctorsVisit
group by
UserID) as b
on a.UserID = b.UserID and a.Date = b.LatestDate;
Note that the User table isn't used at all.
This average omits entirely users who have no doctors visits at all, or whose weight is recorded as NULL in their latest doctors visit. This average is skewed if any users have more than one visit on the same date, and if the latest date is one of those date where the user got wighed more than once.