Distinct Clause not working in SQL Server 2005 - sql

I have so many records having duplicate taskid assigned to multiple person, but i want to show distinct records means only one taskid in output in SQL
Below is my query not working give me solution
SELECT DISTINCT
taskid, taskname, person, userid, dept, date, status, monitor,
comments, monitor_comments, respondtime, assignedby,
reassigncomment, priority,date_complete, followup_date, re_status
FROM
task
WHERE
(status IS NULL)

in your case, result is distinct but not of your desire because you need only distinct task id then you should use this:
SELECT DISTINCT taskid
FROM task
WHERE (status IS NULL)
then result would be distinct task ids.

First, if you have a column called taskid in a table called task, I think it should be unique -- unless it is somehow a slowly changing dimension.
If it is not unique, then you are begging the question: which row do you want?
In any case, SQL Server 2005 have a function called row_number() that can solve your problem:
select t.*
from (select t.*, row_number() over (partition by taskid order by taskid) as seqnum
from task
) t
where seqnum = 1;
This will return one arbitrary row for each taskid. If you have a way of preferring one row over another, then adjust the order by clause.

i have added a column priority in which the value of that column is 1 of same TASKID and other will be 0 so i can find
SELECT DISTINCT
taskid, taskname, person, userid, dept, date, status, monitor,
comments, monitor_comments, respondtime, assignedby,
reassigncomment, priority,date_complete, followup_date, re_status
FROM
task
WHERE
(status IS NULL) and (priority='1')

Related

SQL to Select lowest value, group by, other field

I'm having a problem writing a query that gives me the other fields after finding the min value of another column. I've tried this:
Select WorkOrder, min(Job), Details
From Jobs
Group by WorkOrder
But it doesn't work.
This gives me a list of the lowest Job number by WorkOrder:
Select WorkOrder, min(Job)
From Jobs
Group by WorkOrder
I want Details of the line item with the lowest Job number. What am I doing wrong?
You may try this query
Select WorkOrder, min(Job), Details
From Jobs
Group by WorkOrder, Details
When you use a GROUP BY clause, everything in your select statement has to either be an aggregate function (like min, max, ect) or has to be included in your GROUP BY clause. Details is not included in your GROUP BY clause, and so the statement won't compile. If you include Details in your GROUP BY clause you will get the min(job) of each combination of WorkOrder and Details, which is probably not what you want.
There are a few ways you can go about solving this problem. IMO the easiest would be to select your min(job) and Workorder, and then to join that result back into the jobs table and select details. To do this your jobs table must have a unique primary key.
SELECT
minWorkOrder.WorkOrder
minWorkOrder.MinJob
Jobs.Details
FROM
(Select Key, WorkOrder, min(Job) as MinJob
From Jobs
Group by Key, WorkOrder) AS minWorkOrder
INNER JOIN Jobs
ON Jobs.Key = minWorkOrder.Key
If your table does not have a unique key, then things get a littler trickier. In the scope of this query, it is probably a safe assumption that every combination of min(Job) and WorkOrder is unique. You can join on both of these fields and yous should get the right answer.
SELECT
minWorkOrder.WorkOrder
minWorkOrder.MinJob
Jobs.Details
FROM
(Select WorkOrder, min(Job) as MinJob
From Jobs
Group by WorkOrder) AS minWorkOrder
INNER JOIN Jobs
ON Jobs.Job = minWorkOrder.MinJob AND Jobs.WorkOrder = minWorkOrder.WorkOrder
you should add min() in your condition like this
Select * From Jobs Where Job in
(Select min_job From (Select WorkOrder ,min(Job) as min_job From Jobs
Group by WorkOrder)
)
You should try this:
SELECT WorkOrder, Details
from Jobs
where Job IN (SELECt min(Job), WorkOrder from Jobs GROUP BY WorkOrder);
I worked with an engineer in my department who provided this working answer:
Select A.WorkOrder, A.Job, A.Details
From(Select WorkOrder, Job, Details, Row_Number()
over( Partition by WorkOrder Order by Job ASC) as Num
From Jobs)A
where A.Num = 1
with cte as
(
select workorder,Job, Details, rank() over (partition by workorder order by job asc) as rnk
from
Jobs
)
select workorder,Job, Details from cte
where rnk = 1
Here we are ranking values in column Job in ascending order, for each workorder. Last WHERE clause rnk = 1 fetches only the Jobs with minimum value for each workorder. In case a workorder has more than 1 jobs with same value, RANK() will assign same rank to them . Hence, if a workorder has more than 1 jobs with minimum value ,this will return all of them.

Extract and concatenate the same field from multiple records in big query

I would like to be able to extract one field from multiple records from within a single table. For example, assuming I have a schema as follows
userId, eventTimestamp, theField
And what I want to do is be able to concatenate all instances of the field 'theField' together into a single string for a given userId ordered by eventTimestamp. And for an extra wrinkle, lets say I only want to include the first fiftiest oldest records.
My first attempt was to try something like:
SELECT
userId,
eventTimestamp,
LEAD(theField,0) OVER (PARTITION BY userId ORDER BY eventTimestamp) AS step0,
LEAD(theField,1) OVER (PARTITION BY userId ORDER BY eventTimestamp) AS step1,
....,
LEAD(theField,50) OVER (PARTITION BY userId ORDER BY eventTimestamp) AS step50,
And then the next step was to wrap that first step up in another SELECT statement as follows:
SELECT userId, eventTimestamp, CONCAT(STRING(step0), STRING(step1),...,STRING(step50)) as concatenatedString
FROM [whateverDataset.whateverTable],
GROUP BY
userId, eventTimestamp
This approach doesn't work though because if I have more than 50 steps (which I do), then I end up getting multiple rows for each of those outer SELECT statements, basically N-50 rows, where N = the total number of records for a particular userId. A 'solution' to this would be to have a HAVING statement in the inner SELECT statement to limit itself to only reporting the first 50 records, but overall this seems like a rather cumbersome solution. In non-BigQuery variants of SQL the GROUP_CONCAT seems to be a good way to go forward, but it either doesn't work here or I lack the creativity to get it to work. Anyone have any suggestions?
Thanks,
Brad
For BigQuery Legacy SQL:
SELECT
userid, GROUP_CONCAT(theField) AS Fields
FROM (
SELECT
userid, eventTimestamp, theField,
ROW_NUMBER() OVER(PARTITION BY userid ORDER BY eventTimestamp DESC) AS pos
FROM YourTable
ORDER BY eventTimestamp
)
WHERE pos < 51
GROUP BY userid
Please note: inner ORDER BY does not guarantee the order of theField in GROUP_CONCAT. But, so far, in all practical cases I see the order is carrying. So, test carefuly
For BigQuery Standard SQL:
Don't forget to uncheck Use Legacy SQL checkbox under Show Options
SELECT
userid,
(SELECT STRING_AGG(fields) FROM t.fields) AS fields
FROM (
SELECT
userid,
ARRAY(SELECT theField FROM t.fields ORDER BY eventTimestamp) fields
FROM (
SELECT
userid,
ARRAY_AGG(STRUCT(theField, eventTimestamp)) fields
FROM (
SELECT
userid,
eventTimestamp,
theField,
ROW_NUMBER() OVER(PARTITION BY userid ORDER BY eventTimestamp DESC) AS pos
FROM YourTable
)
WHERE pos < 51
GROUP BY userid
) t
) t

MS Access SQL error

This code is supposed to select the TOP 1, but it's not working properly. Instead of showing only the TOP 1 record, it is showing tons of records. It may be because I have 2 tables referenced. In another code I only had 1 and it worked. I need to reference table attendance though so I'm not sure how to work around that. Thanks!
SELECT TOP 1 userID
FROM attendance, CFRRR
WHERE [attendance.Programs] LIKE CFRRR.program
AND [attendance.Language] LIKE CFRRR.language
AND [attendance.Status] = 'Available'
ORDER BY TS ASC
Here are the table fields for attendance: userID, username, Supervisor, Category, AttendanceDay, AttendanceTime, Programs, Language, Status, TS.
Here are the table fields for CFRRR: CFRRRID, WorkerID, Workeremail, Workername, Dateassigned, assignedby, RRRmonth, Scheduledate, scheduledtime, type, ScheduledType, caseid, language, lastname, firstname, Checkedin, Qid, status, CompletedType, comments, actiondate, verifduedate, program.
Clearly the last table has a lot of records.
SELECT TOP in MS Access differs from SELECT TOP in SQL Server and similar functionality in other databases. It returns the top rows based on the order by. Then it continues to return rows that match the last value. This is convenient sometimes, which is why SQL Server has this functionality as SELECT TOP WITH TIES.
To fix this, you need to include one or more columns that is unique for each generated row:
SELECT TOP 1 userID
FROM attendance as a,
CFRRR
WHERE a.Programs LIKE CFRRR.program AND
a.Language LIKE CFRRR.language AND
a.Status = 'Available'
ORDER BY TS ASC, userId, CFFRID

Trouble with computed column in SQL

I have a table that I wish to select a subset of columns from but also add on the end a computed column based upon where you are located in a queue. There are the following fields (that are pertinent):
id: int, auto increment, primary key
answertime: datetime, nullable
By default, when something is submitted to the queue, its answertime is NULL. So, I wish to select the ID of the thing in the queue as well as its rank in the queue (i.e. rank 1 is the next item that is unanswered, etc). Here's what I was thinking:
rank - id - COUNT(ids below my id where answertime is not null). However, I'm having an issue with the syntax of this query:
SELECT id AS outerid, COUNT(
SELECT * FROM tablename WHERE id<outerid AND answertime IS NOT NULL
)
FROM tablename
WHERE answertime IS NULL;
Now, obviously, this is wrong because I'm fairly confident you can't embed a select inside of an aggregate function, likewise flipping the SELECT and COUNT doesn't work as you can't embed a SELECT at that point in the code (it can only be used in a WHERE clause).
Is this even possible to do with just SQL or do I need to add some logic on the program end?
If it helps, I'm doing this on SQL Server 2008, although I doubt that would add any value.
You can do that, you just can't use SELECT * in an aggregate sub-query. Try this, which gets the COUNT value as a scalar result:
SELECT
id AS outerid,
(SELECT COUNT(Id) FROM tablename
WHERE id<outie.id AND answertime IS NOT NULL)
FROM tablename outie
WHERE answertime IS NULL;
You may need to choose for yourself between using COUNT(*), COUNT(Id) or some other column depending on what you're really after.
SELECT id AS outerid,
(SELECT COUNT(*) FROM tablename WHERE id < outerid AND answertime IS NOT NULL) AS othercol
FROM tablename -- ?
WHERE answertime IS NULL;
also, where's the FROM statement?
As suggested by #HLGEM, you could use ROW_NUMBER() to obtain your results. The method involves ranking the rows in tablename by id without partitioning and by id with partitioning by answertime. The difference between the rankings for every row where answertime is NULL would give you the same value as the one you are calculating using COUNT() in the subquery.
Here's an implementation of the method:
;
WITH ranked AS (
SELECT
*,
Rnk = ROW_NUMBER() OVER ( ORDER BY id),
PartRnk = ROW_NUMBER() OVER (PARTITION BY answertime ORDER BY id)
FROM tablename
)
SELECT
id, /* AS outerid, if you like */
Cnt = Rnk - PartRnk
FROM ranked
WHERE answertime IS NULL

How do I use ROW_NUMBER()?

I want to use the ROW_NUMBER() to get...
To get the max(ROW_NUMBER()) --> Or i guess this would also be the count of all rows
I tried doing:
SELECT max(ROW_NUMBER() OVER(ORDER BY UserId)) FROM Users
but it didn't seem to work...
To get ROW_NUMBER() using a given piece of information, ie. if I have a name and I want to know what row the name came from.
I assume it would be something similar to what I tried for #1
SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'
but this didn't work either...
Any Ideas?
For the first question, why not just use?
SELECT COUNT(*) FROM myTable
to get the count.
And for the second question, the primary key of the row is what should be used to identify a particular row. Don't try and use the row number for that.
If you returned Row_Number() in your main query,
SELECT ROW_NUMBER() OVER (Order by Id) AS RowNumber, Field1, Field2, Field3
FROM User
Then when you want to go 5 rows back then you can take the current row number and use the following query to determine the row with currentrow -5
SELECT us.Id
FROM (SELECT ROW_NUMBER() OVER (ORDER BY id) AS Row, Id
FROM User ) us
WHERE Row = CurrentRow - 5
Though I agree with others that you could use count() to get the total number of rows, here is how you can use the row_count():
To get the total no of rows:
with temp as (
select row_number() over (order by id) as rownum
from table_name
)
select max(rownum) from temp
To get the row numbers where name is Matt:
with temp as (
select name, row_number() over (order by id) as rownum
from table_name
)
select rownum from temp where name like 'Matt'
You can further use min(rownum) or max(rownum) to get the first or last row for Matt respectively.
These were very simple implementations of row_number(). You can use it for more complex grouping. Check out my response on Advanced grouping without using a sub query
If you need to return the table's total row count, you can use an alternative way to the SELECT COUNT(*) statement.
Because SELECT COUNT(*) makes a full table scan to return the row count, it can take very long time for a large table. You can use the sysindexes system table instead in this case. There is a ROWS column that contains the total row count for each table in your database. You can use the following select statement:
SELECT rows FROM sysindexes WHERE id = OBJECT_ID('table_name') AND indid < 2
This will drastically reduce the time your query takes.
You can use this for get first record where has clause
SELECT TOP(1) * , ROW_NUMBER() OVER(ORDER BY UserId) AS rownum
FROM Users
WHERE UserName = 'Joe'
ORDER BY rownum ASC
ROW_NUMBER() returns a unique number for each row starting with 1. You can easily use this by simply writing:
ROW_NUMBER() OVER (ORDER BY 'Column_Name' DESC) as ROW_NUMBER
May not be related to the question here. But I found it could be useful when using ROW_NUMBER -
SELECT *,
ROW_NUMBER() OVER (ORDER BY (SELECT 100)) AS Any_ID
FROM #Any_Table
select
Ml.Hid,
ml.blockid,
row_number() over (partition by ml.blockid order by Ml.Hid desc) as rownumber,
H.HNAME
from MIT_LeadBechmarkHamletwise ML
join [MT.HAMLE] h on ML.Hid=h.HID
SELECT num, UserName FROM
(SELECT UserName, ROW_NUMBER() OVER(ORDER BY UserId) AS num
From Users) AS numbered
WHERE UserName='Joe'
You can use Row_Number for limit query result.
Example:
SELECT * FROM (
select row_number() OVER (order by createtime desc) AS ROWINDEX,*
from TABLENAME ) TB
WHERE TB.ROWINDEX between 0 and 10
--
With above query, I will get PAGE 1 of results from TABLENAME.
If you absolutely want to use ROW_NUMBER for this (instead of count(*)) you can always use:
SELECT TOP 1 ROW_NUMBER() OVER (ORDER BY Id)
FROM USERS
ORDER BY ROW_NUMBER() OVER (ORDER BY Id) DESC
Need to create virtual table by using WITH table AS, which is mention in given Query.
By using this virtual table, you can perform CRUD operation w.r.t row_number.
QUERY:
WITH table AS
-
(SELECT row_number() OVER(ORDER BY UserId) rn, * FROM Users)
-
SELECT * FROM table WHERE UserName='Joe'
-
You can use INSERT, UPDATE or DELETE in last sentence by in spite of SELECT.
SQL Row_Number() function is to sort and assign an order number to data rows in related record set. So it is used to number rows, for example to identify the top 10 rows which have the highest order amount or identify the order of each customer which is the highest amount, etc.
If you want to sort the dataset and number each row by seperating them into categories we use Row_Number() with Partition By clause. For example, sorting orders of each customer within itself where the dataset contains all orders, etc.
SELECT
SalesOrderNumber,
CustomerId,
SubTotal,
ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY SubTotal DESC) rn
FROM Sales.SalesOrderHeader
But as I understand you want to calculate the number of rows of grouped by a column. To visualize the requirement, if you want to see the count of all orders of the related customer as a seperate column besides order info, you can use COUNT() aggregation function with Partition By clause
For example,
SELECT
SalesOrderNumber,
CustomerId,
COUNT(*) OVER (PARTITION BY CustomerId) CustomerOrderCount
FROM Sales.SalesOrderHeader
This query:
SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'
will return all rows where the UserName is 'Joe' UNLESS you have no UserName='Joe'
They will be listed in order of UserID and the row_number field will start with 1 and increment however many rows contain UserName='Joe'
If it does not work for you then your WHERE command has an issue OR there is no UserID in the table. Check spelling for both fields UserID and UserName.