Conditional for a field generated by a SELECT statement - sql

SELECT
Req_PK,
Req_PostDate,
Req_code,
Req_CreateDate,
Req_FillDate,
Req_Canceldate,
Req_Hold,
(
Select Convert(varchar(50),Count(CanReq_PK))
From CanReq
Where CanReq_ReqFK = Req_PK) AS Applications,
Req_PublishstatusFK
FROM Req
WHERE Req_Filled <> 1
AND Req_Cancelled <> 1
AND Req_Template <> 1
AND Req_PublishstatusFK = 1
AND Req_publishstatusfk = 1
How do I modify this query so the Applications field/alias is not the everything returned by the SELECT statement but everything except the ones with value '0'?
Help is very much appreciated!

Use an explicit JOIN instead:
SELECT r.Req_PK, r.Req_PostDate, r.Req_code, r.Req_CreateDate, r.Req_FillDate,
r.Req_Canceldate, r.Req_Hold,
cr.num_Applications,
r.Req_PublishstatusFK
FROM Req r JOIN
(SELECT cr.CanReq_ReqFK, Count(*) as num_applications
FROM CanReq cr
GROUP BY cr.CanReq_ReqFK
) cr
ON cr.CanReq_ReqFK = r.Req_PK
WHERE r.Req_Filled <> 1 AND r.Req_Cancelled <> 1 AND r.Req_Template <> 1 AND
r.Req_PublishstatusFK = 1 AND r.Req_publishstatusfk = 1;
This will filter out any rows that don't have a record in CanReq -- the ones that would have a count of 0 in your version of the query.
I don't know why you would want the count to be a string. Of course, you can include the conversion if you need it, but it doesn't seem necessary to me.

Related

I just started learning SQL and I couldn't do the query, can you help me?

There is a field in the sql query that I can't do. First of all, a new column must be added to the table below. The value of this column needs to be percent complete, so it's a percentage value. So for example, there are 7 values from Cupboard=1 shelves. Where IsCounted is here, 3 of them are counted. In other words, those with Cupboard = 1 should write the percentage value of 3/7 as the value in the new column to be created. If the IsCounted of the others is 0, it will write zero percent. How can I do this?
My Sql Code:
SELECT a.RegionName,
a.Cupboard,
a.Shelf,
(CASE WHEN ToplamSayım > 0 THEN 1 ELSE 0 END) AS IsCounted
FROM (SELECT p.RegionName,
r.Shelf,
r.Cupboard,
(SELECT COUNT(*)
FROM FAZIKI.dbo.PM_ProductCountingNew
WHERE RegionCupboardShelfTypeId = r.Id) AS ToplamSayım
FROM FAZIKI.dbo.DF_PMRegionType p
JOIN FAZIKI.dbo.DF_PMRegionCupboardShelfType r ON p.Id = r.RegionTypeId
WHERE p.WarehouseId = 45) a
ORDER BY a.RegionName;
The result is as in the picture below:
It looks like a windowed AVG should do the trick, although it's not entirely clear what the partitioning column should be.
The SELECT COUNT can be simplified to an EXISTS
SELECT a.RegionName,
a.Cupboard,
a.Shelf,
a.IsCounted,
AVG(a.IsCounted * 1.0) OVER (PARTITION BY a.RegionName, a.Cupboard) Percentage
FROM (
SELECT p.RegionName,
r.Shelf,
r.Cupboard,
CASE WHEN EXISTS (SELECT 1
FROM FAZIKI.dbo.PM_ProductCountingNew pcn
WHERE pcn.RegionCupboardShelfTypeId = r.Id
) THEN 1 ELSE 0 END AS IsCounted
FROM FAZIKI.dbo.DF_PMRegionType p
JOIN FAZIKI.dbo.DF_PMRegionCupboardShelfType r ON p.Id = r.RegionTypeId
WHERE p.WarehouseId = 45
) a
ORDER BY a.RegionName;

SQL Query - Select one row or the other based on the condition

I have the following query producing the given result.
SELECT
p.BookingID, p.PaxID, p.LeadPax, p.FirstName AS LeadPaxName
FROM
[dbo].[BookingV2_Pax] p
WHERE
p.[LeadPax] = 1
UNION
SELECT
PN.BookingID, PN.PaxID, PN.LeadPax, PN.LeadPaxName
FROM
(SELECT
p.BookingID, p.PaxID, p.LeadPax, p.FirstName AS LeadPaxName,
ROW_NUMBER() OVER (PARTITION BY p.BookingID ORDER BY p.PaxID) AS rn
FROM
[dbo].[BookingV2_Pax] p
WHERE
p.[LeadPax] = 0) PN
WHERE
PN.rn = 1
Results:
What I'm doing here is selecting the row which has LeadPax = true and selecting the first row from the other rows which has LeadPax = false
What I want is selecting the either the row with LeadPax = 1 OR LeadPax = 0.
I understand that if this were a column related problem, I can use CASE or COALESCE but how do I do this with rows efficiently?
Also, any pointers on how to optimize the original query would be highly appreciated
Here is one way
Generate the row number only when LeadPax = False. Then use AND/OR logic to get the relevant data
SELECT PN.BookingID,
PN.PaxID,
PN.LeadPax,
PN.LeadPaxName
FROM (SELECT p.BookingID,
p.PaxID,
p.LeadPax,
p.FirstName AS LeadPaxName,
case when PN.[LeadPax] = 0 then Row_number() OVER (partition BY p.BookingID ORDER BY p.PaxID)
else 1 end AS rn
FROM [dbo].[BookingV2_Pax] p) PN
WHERE ( PN.rn = 1 AND PN.[LeadPax] = 0 )
OR PN.[LeadPax] = 1

Union different tables with differents columns and data

My problem is that I have 4 differents SELECT with
SELECT COUNT (*) AS regular
WHERE experience = 1 AND bl = 1
SELECT COUNT (*) AS rptmm
WHERE experience = 1 AND bl = 0
SELECT COUNT (*) AS new
WHERE experience = 0 AND bl = 0
SELECT COUNT (*) AS rptss
WHERE experience = 0 AND bl = 1
I want that the results appear together whith the respective names like:
regular rptmm new rptss
10 5 2 6
Firstly, I'd suggest not to use Count()*. There are many answers on this site explaining why so I am not going to repeat it.
Instead, I'd suggest you to use a query like this:
SELECT (SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 1 AND tab.bl = 1) AS 'Regular',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 1 AND tab.bl = 0) AS 'rptmm',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 0 AND tab.bl = 0) AS 'New',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 0 AND tab.bl = 1) AS 'rptss'
Hope this helps!!!
Just put UNION ALL between your four statements you will get four rows with each count on its own row. However, you will lose the column name. You could also use join to get one row with four columnes. Just put the keyword join between each sql statement.
SELECT COUNT (*) AS regular
WHERE experience = 1 AND bl = 1
JOIN
SELECT COUNT (*) AS rptmm
WHERE experience = 1 AND bl = 0
JOIN
SELECT COUNT (*) AS new
WHERE experience = 0 AND bl = 0
JOIN
SELECT COUNT (*) AS rptss
WHERE experience = 0 AND bl = 1
You could create a temp table to hold all of this data for you: Replace Name1, Name2, Name3,Name4 with whatever you want to call them. These will be the column headers.
CREATE TABLE #Temp(
NAME1 INT
,NAME2 INT
,NAME3 INT
,NAME4 INT
)
INSERT INTO #Temp
(NAME1)
SELECT COUNT(*) AS regular
WHERE experience = 1 AND bl = 1
INSERT INTO #Temp
(NAME2)
SELECT COUNT(*) AS regular
WHERE experience = 1 AND bl = 0
INSERT INTO #Temp
(NAME3)
SELECT COUNT(*) AS regular
WHERE experience = 0 AND bl = 0
INSERT INTO #Temp
(NAME4)
SELECT COUNT(*) AS regular
WHERE experience = 0 AND bl = 1*
SELECT * FROM #Temp

SQL Calculate Percentage on 2 columns

I have a problem, I need to calculate the percentage between 2 different columns. Unfortunately I can't get it to work and when I run this all I get is "Invalid column name 'CountOfPlannedVisits'" & "Invalid column name 'CountOfPlannedVisitsClosed'"
SELECT Count(*) As CountOfPlannedVisits, MAX(datename(month, dbo.tblVisit.DateConfirmed)) AS MonthName,
SUM(CASE WHEN tblVisit.VisitTypeRef <> '5' THEN 1 ELSE 0 END) AS CountOfPlannedVisitsClosed, CAST(100.0 * SUM("CountOfPlannedVisits") / SUM(CountOfPlannedVisitsClosed) AS Decimal(5,2) ) As OverallAttendance
FROM dbo.tblContract INNER JOIN
dbo.tblCustomer ON dbo.tblContract.CustomerRef = dbo.tblCustomer.CustomerID INNER JOIN
dbo.tblContractSite ON dbo.tblContract.ContractID = dbo.tblContractSite.ContractRef INNER JOIN
dbo.tblVisit ON dbo.tblContractSite.CardNumber = dbo.tblVisit.CardNumber
WHERE (tblCustomer.CustomerNumber = '08434')
AND (tblVisit.Routine = '1')
AND year(tblVisit.DateConfirmed) = Year('2013')--#DateYear)
AND dbo.IsOnHoldEx(tblContract.OnHold, tblContractSite.OnHold, tblContract.OnHoldStartDate, tblContract.OnHoldEndDate, tblContractSite.OnHoldStartDate, tblContractSite.OnHoldEndDate) = 0
AND tblVisit.Deleted = 0 -- make sure we dont pull through deleted visits
AND (tblContractSite.DateInactive is NULL or tblContractSite.DateInactive > GetDate())
GROUP BY month(dbo.tblVisit.DateConfirmed)
Any help would be greatly appreciated as I'm not really sure where to go from here!
Thanks
You can only reference a column alias (like CountOfPlannedVisits in your case) in the order by clause. Anywhere else you have to repeat the expression or use a subquery table, something like :
select CountOfPlannedVisits,
CountOfPlannedVisitsClosed,
100 * CountOfPlannedVisits / CountOfPlannedVisitsClosed, ...
from (
select some_expression as CountOfPlannedVisits ,
some_other_expression as CountOfPlannedVisitsClosed
....
) a_table
....

2 Conditions for the same column in a SQl query

How can i get the distinct dates in a table where R.TypeofDayID = 2 and it should not include dates with R.TypeofDayID = 1
I can get all the distinct dates for R.TypeofDayID = 2 using the below query but i am not sure how i can add a condition to get dates where TypeofDayID = 2 and the date should not have TypeofDayID = 1 in any row.
Select count(distinct(R.Date)) from RepInfo R
where R.TypeofDayID = 2 and Month(R.Date) = 2 and Year(R.Date) = 2013
I hope i am clear. This is in SQL Server 2005. Thank you in advance!
Select R.Date, count(*) as cnt
from RepInfo R
where Month(R.Date) = 2 and Year(R.Date) = 2013
group by R.Date
having sum(case when TypeofDayID <> 2 then 1 else 0 end) = 0
Why are you using a COUNT() function in your select statement if you want the the output to be a list of distinct dates? Would you get your desired result from changing your select to something like this:
Select distinct(R.Date)