Querying in SQL- - sql-server

I have a table named "Results" like below:
I'd like to count personnel who have been completely scored. It means the ones who have no zero in score column. For example based on the uploaded picture just person with ID 1004 should be counted and the outcome should be one.
I used this code:
select Count(PrsID) from results
where Score <> 0
group by PrsID
But it wouldn't help me cause if a person has just one non-zero score, he will be counted!
Thanks in advance.

If I understand you correctly, I think this is what you want: SELECT COUNT(DISTINCT(PrsID)) FROM results WHERE PrsID NOT IN (SELECT DISTINCT PrsID FROM results WHERE score = 0)

If a person's min score is greater than zero, then they should be counted.
select count(1)
from (
select PrsID
from results
group by PrsID
having min(Score) > 0) as results

You can use conditional aggregation as below:
Select PrsId from results
group by PrsId
having sum(case when score = 0 then 1 else 0 end) > 1

I think you want something like:
select PrsID, Count(1) from results
where Score = 0
group by PrsID

This one returns count of person who has non zero score
SELECT
t1.PrsID,
Count(t1.PrsID)
FROM
( SELECT
*
FROM results
GROUP BY results.PrsID
ORDER BY results.Score ASC
) AS t1
WHERE t1.Score <> 0;

Related

If subquery returns no rows, return 0 else return value of the subquery

I got a question and you can most likely help me.
I have got a query with a subquery that narrows the search. The query ends with this.
SELECT
*
FROM
Purchase
WHERE
Total < 5000
AND
Total >
(
SELECT TOP 1
buyamount
FROM
employee
WHERE
manager = 'TST'
ORDER BY
buyamount ASC
)
ORDER BY Date DESC
I want the value of the subquery after the ">"... but if the subquery gives nothing in return, i want it to be 0. How do i do this?
In the example you posted you could simply wrap the subquery in COALESCE and get your desired result.
SELECT
*
FROM
#Purchase
WHERE
Total < 5000
AND
Total > COALESCE(
(
SELECT TOP 1
buyamount
FROM
#employee
WHERE
manager = 'TST'
ORDER BY
buyamount ASC
), 0)
ORDER BY Date DESC
You could also use a variable in your provided example instead of a subquery. I prefer this approach because it separates the logic, making it easier to read. Subqueries can also be a performance killer. Having it broken out like this, it should perform better.
DECLARE #BuyAmount INT
SET #BuyAmount = (SELECT TOP 1 BuyAmount FROM #Employee WHERE Manager = 'TST' ORDER BY BuyAmount ASC)
IF #BuyAmount IS NULL SET #BuyAmount = 0
SELECT *
FROM #Purchase
WHERE Total < 5000 AND Total > #BuyAmount
ORDER BY Date DESC

SQL Server : Combining Query Results

I have a program that stores different types "Assets" for buildings which can be marked as being "Removed". I can create a query to count the number of assets by type and another to count the number of items identified as still present. But what I want to do is combine the two into 1 table.
Query 1
SELECT
theAssetOutletType, COUNT(id) AS TotalNoOfAssets
FROM
dbo.tblLEGAssets
WHERE
buildingID = 1
GROUP BY
theAssetOutletType
Query 2
SELECT
theAssetOutletType, COUNT(id) AS ItemsStillPresent
FROM
dbo.tblLEGAssets
WHERE
buildingID = 1 AND removed <> 0
GROUP BY
theAssetOutletType
Thank you in advance for any help
I would suggest conditional aggregation:
SELECT theAssetOutletType,
COUNT(*) as TotalNoOfAssets
SUM(CASE WHEN removed <> 0 THEN 1 ELSE 0 END) as ItemsStillPresent
FROM dbo.tblLEGAssets
WHERE buildingID = 1
GROUP BY theAssetOutletType;
This puts the values in separate columns on the same row -- which makes more sense to me than on separate rows.
Try Union:
SELECT theAssetOutletType, count(id) as TotalNoOfAssets FROM dbo.tblLEGAssets where buildingID=1 group by theAssetOutletType
UNION
SELECT theAssetOutletType, count(id) as ItemsStillPresent FROM dbo.tblLEGAssets where buildingID=1 and removed<> 0 group by theAssetOutletType
I've found a work around, by using a nested select - that I can use, but if it is still possible I'd love to know the answer:
SELECT theassetoutlettype,
noofitems,
noremoved,
noofitems - noremoved AS noLeft
FROM (SELECT theassetoutlettype,
Count(id) AS NoOfItems,
Sum(removed) AS noRemoved
FROM dbo.tbllegassets
WHERE buildingid = 1
GROUP BY theassetoutlettype) nested
I finally found a solution... took a lot of trial and error but it now works. Here is my Stored Procedure Solution, with the additional table "tblLEGAssetOutletTypes" which contains a single fields with a list of the 6 asset types. The following code will always return 6 rows with the project type, the total number of assets, the number of assets removed and the total remaining. Hope someone else who needs a similar problem resolving an use the code:
SELECT tblLEGAssetOutletTypes.assetOutletType, nested.NoOfItems, nested.noRemoved, NoOfItems-noRemoved AS noLeft
FROM (SELECT theAssetOutletType, COUNT(id) AS NoOfItems, SUM(removed) AS noRemoved
FROM tblLEGAssets
where buildingID=#buildingID
GROUP BY theAssetOutletType) AS nested
RIGHT JOIN tblLEGAssetOutletTypes ON nested.theAssetOutletType = tblLEGAssetOutletTypes.assetOutletType;

select statement with "Group by" on specific columns but displaying other columns along with group by columns

I want to get all data based on group by of only encounter,medicationname
column data..
select encounter,medicationname,count(*) as freq,labdate,result
from Medications where (labdate between #admitdate and DATEDIFF(dd,24,#admitdate))
group by encounter,medicationname having count(*)>2
I have records like
encounter medicationname freq
8604261 ACC 3
Now based on this data ,I want to get
This is my desired output
encounter medicationname labtime result
8604261 ACC 2015-05-22 18
8604261 ACC 2015-07-23 23
8604261 ACC 2015-09-09 27
You can use COUNT() as a window function, something like this:
;With Counted as (
SELECT encounter,medicationname,labdate,result,
COUNT(*) OVER (PARTITION BY encounter,medicationname) as cnt
from Medications
where (labdate between #admitdate
and DATEDIFF(dd,24,#admitdate))
)
select encounter,medicationname,labdate,result
from Counted
where cnt > 2
I would note that I think DATEDIFF1 is probably wrong also but since I don't have your data, inputs and an actual spec, I've left it as is for now.
1DATEDIFF returns an int, but you're using it in a comparison against a column which is apparently a date. DATEADD would be the more probably desired function here, but as I say, I don't have full information to go on.
If I understand you question correctly what you need is this
;WITH CTE AS
(
select encounter,medicationname,count(*) as freq,labdate,result
from Medications where (labdate between #admitdate and DATEDIFF(dd,24,#admitdate))
group by encounter,medicationname having count(*) > 2
)
select encounter,medicationname,labdate,result
from Medications M
INNER JOIN CTE C
ON M.encounter = C.encounter
AND M.medicationname = C.medicationname
where (labdate between #admitdate and DATEDIFF(dd,24,#admitdate))
or better yet using COUNT()OVER()
;WITH CTE AS
(
SELECT encounter,medicationname,COUNT(*) OVER(PARTITION BY encounter,medicationname)as freq,labdate,result
FROM Medications
WHERE (labdate between #admitdate and DATEDIFF(dd,24,#admitdate))
)
SELECT * FROM CTE
WHERE freq > 2
select encounter,medicationname,count(*) as freq,labdate,result
from Medications
where (labdate between #admitdate and DATEDIFF(dd,24,#admitdate))
group by encounter,medicationname having count(*) > 2

mssql - select from another table if no results from the first table

I have to run a query to find a price. I have multiple price lists, each in their own table. customer_price, default_price and minimum_price.
not all price lists have all the products and at times a product might not appear on any price list and then the price needs to return 0 for the price.
so I want to:
select price from customer_price where customer='walmart' and product='whitebread'
if this returns a result then all is well. if the result is 0,NULL or the query returns no rows I want this to run:
select price from default_price where customer='walmart' and product='whitebread'
if this returns a result then all is well. if the result is 0,NULL or the query returns no rows I want to simply return 0.
I am not sure how to proceed. I tried a case statement but the case statement fails if no row is found in the results. how can I do this or say if 0 results then
thanks in advance, as always.
select top 1 price from (
select 1 as qorder, price from customer_price where price > 0 and customer='walmart' and product='whitebread'
union
select 2 as qorder, price from default_price where price > 0 and customer='walmart' and product='whitebread'
union
select 3 as qorder, 0
) as sq
order by qOrder
case when
(select count(price) from customer_price where customer='walmart' and product='whitebread' and price is not null and price > 0) > 0
then
select price from customer_price where customer='walmart' and product='whitebread'
else
select price from default_price where customer='walmart' and product='whitebread'
end
I'm writing a two way solution which includes for both Empty Select Queries or Tables. You can replace your query
if OBJECT_ID('tempdb..#temp1') is not null
drop table #temp1
select * into #temp1 from (select col1, col2 from First_Table) as firstTableVariable
if (##ROWCOUNT > 0)
begin
print 'data is displayed from the first table/query'
select * from #temp1
end
else
begin
print 'Data displayed from second table/query '
select col1, col2 from second_Table
end
end

If any clause when grouping

Doing a Sum() on a column adds up the values in that column based on group by. But lets say I want to sum these values only if all the values are not null or not 0, then I need a clause which checks if any of the values is 0 before it does the sum. How can I implement such a clause?
I'm using sql server 2005.
Thanks,
Barry
Let's supose your table schema is:
myTable( id, colA, value)
Then, one approach is:
Select colA, sum(value)
from myTable
group by colA
having count( id ) = count( nullif( value, 0 ))
Notice that nullif is a MSSQL server function. YOu should adapt code to your rdbms brand.
Explanation:
count aggregate function only count not null values. Here a counting null values test.
You say that 0+2+3=0 for this case. Assuming that NULL+2+3 should also be zero:
SELECT GroupField,
SUM(Value) * MIN(CASE WHEN COALESCE(Value, 0) = 0 THEN 0 ELSE 1 END)
FROM SumNonZero
GROUP BY GroupField
The above statement gives this result
GroupField (No column name)
case1 5
case2 0
case3 0
with this test data
CREATE TABLE SumNonZero (
GroupField CHAR(5) NOT NULL,
Value INT
)
INSERT INTO SumNonZero(GroupField, Value)
SELECT 'case1', 2
UNION ALL SELECT 'case1', 3
UNION ALL SELECT 'case2', 0
UNION ALL SELECT 'case2', 2
UNION ALL SELECT 'case2', 3
UNION ALL SELECT 'case3', NULL
UNION ALL SELECT 'case3', 3
UNION ALL SELECT 'case3', 4
It makes no sense to eliminate 0 from a SUM because it wont impact the sum.
But you may want to SUM based on another field:
select FIELD, sum(
case when(OTHER_FIELD>0) then FIELD
else 0
end)
from TABLE
group by TABLE

Resources