Selecting Different rows if the values of one column are equal - sql-server

I am trying to write a SQL query that selects the top 4 from a random query so I can do quality checks on the certain cases. Each case has an account number tied to a client. The problem is that each case has a unique number but may have the same account number.
What I am looking to do is if the account number is the same on two cases to have the SQL select a new row with a different account number.
Select Top 4
Account,
CaseNum
From dbo.tblRequest
Where LoggedDate Between GetDate() - 7 and GetDate() - 1
Order By NewId();
The Results will display 4 accounts but at times it is possible that the same account is displayed twice. As stated I want to only display distinct accounts for a 7 day period.
I have tried the distinct key word and it still displays the accounts twice in some queries results.

Try following statement. using row_number to get only on line for same accountNumber.
SELECT * FROM (
Select
Account,
CaseNum,
ROW_NUMBER()OVER(PARTITION BY Account ORDER BY GETDATE()) AS rn
From dbo.tblRequest
Where LoggedDate Between GetDate() - 7 and GetDate() - 1
) AS t WHERE t.rn=1
Order By
NewId()

Related

SQL Server 2014 Random Value in Group By

I'm trying to figure out how to get a single random row returned per account from a table. The table has multiple rows per account or in some cases just a single row. I want to be able to get a random result back in my select so each day that I run the same statement I might get a different result.
This is basis of the query:
select number, phonenumber
from phones_master with(nolock)
where phonetypeid = '3'
This is a sample result set
number phonenumber
--------------------------
4130772, 6789100949
4130772, 6789257988
4130774, 6784519098
4130775, 6786006874
The column called Number is the account. I'd like to return a single random row. So based on the sample result set above the query should return 3 rows.
Any suggestions would be greatly appreciated. I'm beating my head against the wall with this one.
Thanks
You can use WITH TIES in concert with Row_Number()
Select Top 1 with ties *
From YourTable
Order by Row_Number() over (Partition By Number Order By NewID())
Returns (for example)
number phonenumber
4130772 6789257988
4130774 6784519098
4130775 6786006874
If you have another table called account where those number's are generated/created then here is one way using Cross Apply.
SELECT at.number,
cs.phonenumber
FROM account_table at
CROSS apply(SELECT TOP 1 phonenumber
FROM phones_master pm
WHERE at.number = pm.number
AND phonetypeid = '3'
ORDER BY Newid()) cs (phonenumber)
Also this considers the number in account table is unique.
Creating a Index on number and phonetypeid in phones_master table should improve the performance

Compute sum for distinct order numbers in ssrs report

I'm using a SQL Server 2008R2 Database and SSRS Report Builder 3.0
Trying to compute the sum of the amount owed for each order id (need to show the itemids)...but when I do, the amount owed is showing 400 (instead of 200 - line 4, 100 instead of 50 in line 7, line 9 is correct. As a result the Total line is way off)
=Sum(Fields!owe.Value)
The report is grouped by the campus.
I understand that ssrs is probably not the best place to do this computation but I don't know how to do outside of ssrs....I tried distinct and group by so far with no results.
Below is how I need the report to show like....
Thanks in advance.
Incorrect amounts are
Another example as it should display the subtotals
I would modify the SQL to produce an extra column just for purposes of summing the Owe on an OrderId. Use the Row Number to get the first item in each order, and only supply the Owe value for that item for each order:
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY OrderId ORDER BY ItemId) AS rn
FROM MyTable
WHERE (whatever filters you use)
)
SELECT *,
CASE WHEN rn=1 THEN Owe ELSE 0 END AS OrderOwe
FROM cte
ORDER BY Campus, CustomerId, OrderId, ItemId
Then simply change the expression for the "Owe" textbox in your SubTotal row to this:
=Sum(Fields!OrderOwe.Value)
And you will get the sum of the Owe per order instead of per item.
Well if your owe is always the same for each item in the group you could add a Sum/Count of the item in the group which would give you the correct results in all the cases above.

Need help comparing difference between datetime stamps in SQL DB

I have a MSSQL server 2012 express DB that logs user activities. I need some help creating a query to compare timestamps on the user activities based on the text in the notes. I am interested in figuring out how long it takes my users to perform certain activities. The activities they are performing are stored in text in a NOTES column. I want to build a query that will tell me the time difference for each [INVOICEID] from the ‘START NOTE’ to the next note for that invoice by that user. The note that is entered is always the same for the start of the timer (for the purposes of this I used ‘START NOTE’ to indicate the start of the timer, but I have multiple activites I will need to do this for so I plan on simply changing that text in the query), but the end of the timer the text of the note will vary because it will be user entered data. I want to find the time difference between ‘START NOTE’ and the note that immediately follows ‘START NOTE’ entered by the same USERID for the same INVOICEID. Please see the SQLfiddle for an example of my data:
http://sqlfiddle.com/#!3/a00d7/1
With the data in the sql fiddle I would want the results of this query to be:
INVOICE ID USERID TIME_Difference
100 5 1 day
101 5 3 days
102 5 9 days
(time_difference does not need to be formatted like that, standard SQL formatting is fine)
I don’t really know where to start with this. Please let me know if you can help.
Thanks
select a.userid,a.invoiceid,min(a.added),min(b.added),datediff(DAY,min(a.added),min(b.added)) from om_note a
left join om_note b on a.userid=b.userid and a.invoiceid = b.invoiceid and a.added < b.added
where a.notes = 'START NOTE' group by a.userid,a.invoiceid
;with x as (
select
o.*, sum(case when notes='START NOTE' then 1 else 0 end)
over(partition by o.invoiceid, o.userid order by o.added) as grp
from om_note o
),
y as (
select *,
row_number() over(partition by x.invoiceid, x.userid, x.grp order by x.added) as rn
from x
where grp > 0
)
select y1.invoiceid, y1.userid, datediff(hour, y1.added, y2.added)
from y y1
inner join y y2
on y1.invoiceid=y2.invoiceid and y1.userid=y2.userid and y1.grp=y2.grp
where y1.rn=1 and y2.rn=2

Show records where most recent 'x' records meet criteria

Here's a simplified SQLFiddle example of data
Basically, I'm looking to identify records in a login audit table where the most recent records for each user has 'x' (let's say 3, for this example) number of failed logins
I am able to get this data for individual users by doing a SELECT TOP 3 and ordering by the log date in descending order and evaluating those records, but I know there's got to be a better way to do this.
I have tried a few queries using ROW_NUMBER(), partitioning by UserName and Success and ordering by LogDate, but I can't quite get it to do what I want. Essentially, every time a successful login occurs, I want the failed login counter to be reset.
try this code:
select * from (
select distinct a.UserName,
(select sum(cast(Success as int)) from (
SELECT TOP 3 Success --- here 3, change it to your number
FROM tbl as b
WHERE b.UserName=a.UserName
ORDER BY LogDate DESC
) as q
having count(*) >= 3 --- this string need to remove users who made less then 3 attempts
) as cnts
from tbl as a
) as q2
where q2.cnts=0
it shows users with all last 3 attempts failed, with different modifications, you can use this approach to identify how many success/fail attempts where done during last N rows
NOTE: this query works, but it is not the optimal way, from tbl as a should be changed to table where only users are stored, so you will be able to get rid of distinct, also - store users ID instead of username in tbl

Performant way to get the maximum value of a running total in TSQL

We have a table of transactions which is structured like the following :
TranxID int (PK and Identity field)
ItemID int
TranxDate datetime
TranxAmt money
TranxAmt can be positive or negative, so the running total of this field (for any ItemID) will go up and down as time goes by. Getting the current total is obviously simple, but what I'm after is a performant way of getting the highest value of the running total and the TranxDate when this occurred. Note that TranxDate is not unique, and due to some backdating the ID field is not necessarily in the same sequence as TranxDate for a given Item.
Currently we're doing something like this (#tblTranx is a table variable containing just the transactions for a given Item) :
SELECT Top 1 #HighestTotal = z.TotalToDate, #DateHighest = z.TranxDate
FROM
(SELECT a.TranxDate, a.TranxID, Sum(b.TranxAmt) AS TotalToDate
FROM #tblTranx AS a
INNER JOIN #tblTranx AS b ON a.TranxDate >= b.TranxDate
GROUP BY a.TranxDate, a.TranxID) AS z
ORDER BY z.TotalToDate DESC
(The TranxID grouping removes the issue caused by duplicate date values)
This, for one Item, gives us the HighestTotal and the TranxDate when this occurred. Rather than run this on the fly for tens of thousands of entries, we only calculate this value when the app updates the relevant entry and record the value in another table for use in reporting.
The question is, can this be done in a better way so that we can work out these values on the fly (for multiple items at once) without falling into the RBAR trap (some ItemIDs have hundreds of entries). If so, could this then be adapted to get the highest values of subsets of transactions (based on a TransactionTypeID not included above). I'm currently doing this with SQL Server 2000, but SQL Server 2008 will be taking over soon here so any SQL Server tricks can be used.
SQL Server sucks in calculating running totals.
Here's a solution for your very query (which groups by dates):
WITH q AS
(
SELECT TranxDate, SUM(TranxAmt) AS TranxSum
FROM t_transaction
GROUP BY
TranxDate
),
m (TranxDate, TranxSum) AS
(
SELECT MIN(TranxDate), SUM(TranxAmt)
FROM (
SELECT TOP 1 WITH TIES *
FROM t_transaction
ORDER BY
TranxDate
) q
UNION ALL
SELECT DATEADD(day, 1, m.TranxDate),
m.TranxSum + q.TranxSum
FROM m
CROSS APPLY
(
SELECT TranxSum
FROM q
WHERE q.TranxDate = DATEADD(day, 1, m.TranxDate)
) q
WHERE m.TranxDate <= GETDATE()
)
SELECT TOP 1 *
FROM m
ORDER BY
TranxSum DESC
OPTION (MAXRECURSION 0)
You need to have an index on TranxDate for this to work fast.

Resources