I am having difficulties setting up the following query where I want to:
find all the WORKORDER values in the MATERIALSCOSTACT table that have one of two specific MATERIALID values.
Then from the WORKORDER table I want to weed out all the values with a 'main replace' or 'install' DESCRIPTION and then I want to make sure I am only looking at water or sewer ASSETGROUP. I want to make sure I am only looking at records that have a WOMACOST that have occured since the first of the year.
I would like to inner join the MATERIALSCOSTACT table and the WORKORDER table on their shared WORKORDERID column.
I cant figure out how to join the first statement with teh second, and in the second statement, SQL Server is giving me a syntax error on "INNER"
select workorderid from [CityWorks].[AZTECA].[materialcostact] where materialsid = '30791' or
materialsid = '30841'
Select * from [CityWorks].[AZTECA].[WORKORDER]
where description not like '%main replace%' and description not like '%install%'
and (assetgroup = 'WATER' or Assetgroup = 'SEWER')
and womatcost != 0
and ACTUALSTARTDATE > '2013-12-31 00:00:00.000'
INNER JOIN workorderid on [CityWorks].[AZTECA].[materialcostact].[workorderid] =
[CityWorks].[AZTECA].[WORKORDER].[workorderid]
group by assetgroup
Thank you very much to anyone who can help!
You just have your where clause in the wrong place. It needs to come after the joins.
Select * from [CityWorks].[AZTECA].[WORKORDER]
INNER JOIN workorderid on [CityWorks].[AZTECA].[materialcostact].[workorderid] =
[CityWorks].[AZTECA].[WORKORDER].[workorderid]
where description not like '%main replace%' and description not like '%install%'
and (assetgroup = 'WATER' or Assetgroup = 'SEWER')
and womatcost != 0
and ACTUALSTARTDATE > '2013-12-31 00:00:00.000'
group by assetgroup
You may have to alias your tables or be more explicit in your where clause if those columns occur in more than one table.
I believe this is what you want:
NB: try to use aliases, they make your code easier to read.
Select *
from [CityWorks].[AZTECA].[WORKORDER] WO
JOIN [CityWorks].[AZTECA].[materialcostact] MC
on WO.[workorderid] = MC.[workorderid]
and (MC.materialsid = 30791 or MC.materialsid = 30841)
where description not like '%main replace%' and description not like '%install%'
and (assetgroup = 'WATER' or Assetgroup = 'SEWER')
and womatcost != 0
and ACTUALSTARTDATE >= '2014-01-01'
Related
I need to select grade_name from tblgrade, subject_name from tblsubject, count (subscribe_id) from tblsubcription, count (sub_status) from tblsubcription where sub_status=1 and count (sub_status) from tblsubcription where sub_status is null.
This is what i have tried:
SELECT t2.grade_name,
t.subject_name,
(SELECT COUNT(*)
FROM tblsubcription
WHERE sub_status IS NULL
AND teacher_id = 2) AS pending,
(SELECT COUNT(*)
FROM tblsubcription
WHERE sub_status = '1'
AND teacher_id = 2) AS appoved,
COUNT(t1.subscribe_id) AS totalsub
FROM tblsubject t
INNER JOIN tblsubject_grade tg ON (t.subject_id = tg.subject_id)
INNER JOIN tblsubcription t1 ON (tg.subject_garde_id = t1.subject_garde_id)
INNER JOIN tblgrade t2 ON (tg.grade_id = t2.grade_id)
AND tg.grade_id = t2.grade_id
AND tg.subject_id = t.subject_id
AND t2.admin_id = t.admin_id
WHERE t1.teacher_id = 2
GROUP BY t.subject_name,
t2.grade_name;
See result obtained when the above query is executed and the expected result i need is in red
Looking at this subquery:
(SELECT COUNT(*)
FROM tblsubcription
WHERE sub_status IS NULL
AND teacher_id = 2) AS pending,
There is nothing here to relate (correlate) it to the specific row. You need an additional condition in the WHERE clause that tells you which Grade/Subject pair to look at. The other (approved) subquery is the same way.
Alternatively, you may be able to solve this with another join to tblsubscription and conditional aggregation.
I'd post code to fix this, but I find the images too blurry to read well, so I can't easily infer which fields to use. Next time post formatted text, and you'll get a better answer in less time.
I am trying to combine two SQL queries the first is
SELECT
EAC.Person.FirstName,
EAC.Person.Id,
EAC.Person.LastName,
EAC.Person.EmployeeId,
EAC.Person.IsDeleted,
Controller.Cards.SiteCode,
Controller.Cards.CardCode,
Controller.Cards.ActivationDate,
Controller.Cards.ExpirationDate,
Controller.Cards.Status,
EAC.[Group].Name
FROM
EAC.Person
INNER JOIN
Controller.Cards ON EAC.Person.Id = Controller.Cards.PersonId
INNER JOIN
EAC.GroupPersonMap ON EAC.Person.Id = EAC.GroupPersonMap.PersonId
INNER JOIN
EAC.[Group] ON EAC.GroupPersonMap.GroupId = EAC.[Group].Id
And the second one is
SELECT
IsActive, ActivationDateUTC, ExpirationDateUTC,
Sitecode + '-' + Cardcode AS Credential, 'Badge' AS Type,
CASE
WHEN isActive = 0
THEN 'InActive'
WHEN ActivationDateUTC > GetUTCDate()
THEN 'Pending'
WHEN ExpirationDAteUTC < GetUTCDate()
THEN 'Expired'
ELSE 'Active'
END AS Status
FROM
EAC.Credential
JOIN
EAC.WiegandCredential ON Credential.ID = WiegandCredential.CredentialId
WHERE
PersonID = '32'
Where I would like to run the second query for each user of the first query using EAC.Person.Id instead of the '32'.
I would like all the data to be returned in one Dataset so I can use it in Report Builder.
I have been fighting with this all day and am hoping one of you smart guys can give me a hand. Thanks in advance.
Based on your description in the comments, I understand that the connection between the two datasets is actually the PersonID field, which exists in both EAC.Credential and EAC.Person; however, in EAC.Credential, duplicate values exist for PersonID, and you want only the most recent one for each PersonID.
There are a few ways to do this, and it will depend on the number of rows returned, the indexes, etc., but I think maybe you're looking for something like this...?
SELECT
EAC.Person.FirstName
,EAC.Person.Id
,EAC.Person.LastName
,EAC.Person.EmployeeId
,EAC.Person.IsDeleted
,Controller.Cards.SiteCode
,Controller.Cards.CardCode
,Controller.Cards.ActivationDate
,Controller.Cards.ExpirationDate
,Controller.Cards.Status
,EAC.[Group].Name
,X.IsActive
,X.ActivationDateUTC
,X.ExpirationDateUTC
,X.Credential
,X.Type
,X.Status
FROM EAC.Person
INNER JOIN Controller.Cards
ON EAC.Person.Id = Controller.Cards.PersonId
INNER JOIN EAC.GroupPersonMap
ON EAC.Person.Id = EAC.GroupPersonMap.PersonId
INNER JOIN EAC.[Group]
ON EAC.GroupPersonMap.GroupId = EAC.[Group].Id
CROSS APPLY
(
SELECT TOP 1
IsActive
,ActivationDateUTC
,ExpirationDateUTC
,Sitecode + '-' + Cardcode AS Credential
,'Badge' AS Type
,'Status' =
CASE
WHEN isActive = 0
THEN 'InActive'
WHEN ActivationDateUTC > GETUTCDATE()
THEN 'Pending'
WHEN ExpirationDateUTC < GETUTCDATE()
THEN 'Expired'
ELSE 'Active'
END
FROM EAC.Credential
INNER JOIN EAC.WiegandCredential
ON EAC.Credential.ID = EAC.WiegandCredential.CredentialId
WHERE EAC.Credential.PersonID = EAC.Person.PersonID
ORDER BY EAC.Credential.ID DESC
) AS X
-- Optionally, you can also add conditions to return specific rows, i.e.:
-- WHERE EAC.Person.PersonID = 32
This option uses a CROSS APPLY, which means that every row of the first dataset will return additional values from the second dataset, based on the criteria that you described. In this CROSS APPLY, I'm joining the two datasets based on the fact that PersonID exists in both EAC.Person (in your first dataset) as well as in EAC.Credential. I then specify that I want only the TOP 1 row for each PersonID, with an ORDER BY specifying that we want the most recent (highest) value of ID for each PersonID.
The CROSS APPLY is aliased as "X", so in your original SELECT you now have several values prefixed with the X. alias, which just means that you're taking these fields from the second query and attaching them to your original results.
CROSS APPLY requires that a matching entry exists in both subsets of data, much like an INNER JOIN, so you'll want to check and make sure that the relevant values exist and are returned correctly.
I think this is pretty close to the direction you're trying to go. If not, let me know and I'll update the answer. Good luck!
Try like this;
select Query1.*, Query2.* from (
SELECT
EAC.Person.FirstName,
EAC.Person.Id as PersonId,
EAC.Person.LastName,
EAC.Person.EmployeeId,
EAC.Person.IsDeleted,
Controller.Cards.SiteCode,
Controller.Cards.CardCode,
Controller.Cards.ActivationDate,
Controller.Cards.ExpirationDate,
Controller.Cards.Status,
EAC.[Group].Name
FROM
EAC.Person
INNER JOIN
Controller.Cards ON EAC.Person.Id = Controller.Cards.PersonId
INNER JOIN
EAC.GroupPersonMap ON EAC.Person.Id = EAC.GroupPersonMap.PersonId
INNER JOIN
EAC.[Group] ON EAC.GroupPersonMap.GroupId = EAC.[Group].Id)
Query1 inner join (SELECT top 100
IsActive, ActivationDateUTC, ExpirationDateUTC,
Sitecode + '-' + Cardcode AS Credential, 'Badge' AS Type,
CASE
WHEN isActive = 0
THEN 'InActive'
WHEN ActivationDateUTC > GetUTCDate()
THEN 'Pending'
WHEN ExpirationDAteUTC < GetUTCDate()
THEN 'Expired'
ELSE 'Active'
END AS Status
FROM
EAC.Credential
JOIN
EAC.WiegandCredential ON Credential.ID = WiegandCredential.CredentialId
ORDER BY EAC.Credential.ID DESC) Query2 ON Query1.PersonId = Query2.PersonID
Just select two queries to join them like Query1 and Query2 by equaling PersonId data.
I'm wondering if there is a way to have a complete select statement and if no row is returned to return a row with a default value in a specific field (SQL Server)? Here's a generic version of my SQL to better explain:
SELECT COUNT(CASE WHEN CAST(c.InjuryDate as DATE)>DATEADD(dd,-60, getdate ()) THEN b.InjuryID end) InjuryCount, a.PersonID
FROM Person_Info a
JOIN Injury_Subject b on b.PersonID=a.PersonID
JOIN Injury_Info c on c.InjuryID=b.InjuryID
WHERE EXISTS (SELECT * FROM Hospital_Record d WHERE d.PersonID=b.PersonID and d.InjuryID=b.InjuryID) --There could be multiple people associated with the same InjuryID
GROUP BY a.PersonID
If NOT EXISTS (SELECT * FROM Hospital_Record d WHERE d.PersonID=a.PersonID) THEN '0' in InjuryCount
I want a row for each person who has had an injury to display. Then I'd like a count of how many injuries resulted in hospitalizations in the last 60 days. If they were not hospitalized, I'd like the row to still be generated, but display '0' in InjuryCount column. I've played with this a bunch, moving my date from the WHERE to the SELECT, trying IF ELSE combos, etc. Could someone help me figure out how to get what I want please?
It's hard to tell without an example of input and desired output, but I think this is what you are going for:
select
InjuryCount = count(case
when cast(ii.InjuryDate as date) > dateadd(day,-60,getdate())
then i.InjuryId
else null
end
)
, p.PersonId
from Person_Info p
left join Hosptal_Record h on p.PersonId = h.PersonId
left join Injury_Subject i on i.PersonId = h.PersonId
and h.InjuryId = i.InjuryId
left join Injury_Info ii on ii.InjuryId = i.InjuryId
group by p.PersonId;
I am trying to get a certain set of results with a UNION SELECT, and I am having trouble figuring out how to limit my results accordingly. Essentially I have objects that I am returning and displaying in the form of several of their attributes. One of those attributes is a comment that can be made on the object. Some have comments on them, and some do not. I want to display all that have comments as well as all that do not have comments. The problem I am running into: My first SELECT is returning all of the instances with comments just fine, but my second SELECT which is meant to return the instances without comments, not only does that, but also returns a duplicate instance of the previous, but without a comment. So in the end I have all instances where there is no comment, and if there is a comment, I get in instance with the comment and a duplicate but without the comment. I have pasted my code below, but if you feel there is a better way of doing this other than using a union select, your enlightenment is much appreciated.
Some Background: In my DB, I have my main table of 'Deals' and a Deal can have many comments, and I am using the DealID with a marker to tell if that Comment is active or not.
My Stored Procedure:
#Dealership nvarchar(50)
AS
SELECT DealDate,
DateReceived,
Bounced,
StockNumber,
LocationName,
CustomerName,
Comment
FROM
tVehicleDeal,
tDealerships,
tInternalLocations,
tVehicleComments,
tCustomer
WHERE
(tVehicleDeal.DealershipID = tDealerships.DealershipID)
AND (tDealerships.DealershipName LIKE '%'+#Dealership+'%')
AND tVehicleDeal.InternalLocationID = tInternalLocations.InternalLocationID
AND tVehicleDeal.DealID = tVehicleComments.DealID
AND tVehicleDeal.CustomerID = tCustomer.CustomerID
AND NOT tInternalLocations.LocationName = 'Down Deal'
AND tVehicleDeal.Titled IS NULL
AND tVehicleDeal.Archived = 0
UNION SELECT DealDate,
DateReceived,
Bounced,
StockNumber,
LocationName,
CustomerName,
NULL
FROM
tVehicleDeal,
tDealerships,
tInternalLocations,
tCustomer
WHERE
(tVehicleDeal.DealershipID = tDealerships.DealershipID)
AND (tDealerships.DealershipName LIKE '%'+#Dealership+'%')
AND tVehicleDeal.InternalLocationID = tInternalLocations.InternalLocationID
AND tVehicleDeal.CustomerID = tCustomer.CustomerID
AND NOT tInternalLocations.LocationName = 'Down Deal'
AND tVehicleDeal.Titled IS NULL
AND tVehicleDeal.Archived = 0
ORDER BY [DealDate] ASC
-Thanks in advance!
You need to read up on the SQL-92 Join syntax. You need to use an Outer Join to the comments table.
try this:
SELECT DealDate, DateReceived, Bounced, StockNumber,
LocationName, CustomerName, Comment
FROM tVehicleDeal vd
Join tDealerships d
On d.DealershipID = vd.DealershipID
And d.DealershipName LIKE '%'+#Dealership+'%'
Join tInternalLocations il
On il.InternalLocationID = vd.InternalLocationID
And il.LocationName <> 'Down Deal'
Join tCustomer cu
On cu.CustomerID = vd.CustomerID
Left Join tVehicleComments c
On c.DealID = vd.DealId
WHERE vd.Titled Is Null
And vd.Archived = 0
If the results on both sides aren't EXACTLY the same you'll get both. Since you have the NULL in place of Comment in the second query, the result for that row is different from the result in the first query and thus you get both results.
One way to fix it would be to add a
AND Comment IS NULL
to the second query.
Can I suggest that you
Use JOIN syntax instead of the WHERE
Use a LEFT OUTER JOIN to tVehicleComments
and this way you should be able to avoid the repeated query with the UNION entirely, e.g.
Edit
If you potentially have more than one comment per vehicledeal, you can restrict the output to just one of them by grouping by the remainder of columns and applying an appropriate Aggregation function to the comment, e.g.:
SELECT
DealDate,
DateReceived,
Bounced,
StockNumber,
LocationName,
CustomerName,
MIN(Comment) AS FirstComment
FROM
tVehicleDeal
INNER JOIN tDealerships
ON tVehicleDeal.DealershipID = tDealerships.DealershipID
INNER JOIN tInternalLocations,
ON tVehicleDeal.InternalLocationID = tInternalLocations.InternalLocationID,
LEFT OUTER JOIN tVehicleComments
ON tVehicleDeal.DealID = tVehicleComments.DealID
INNER JOIN tCustomer
ON tVehicleDeal.CustomerID = tCustomer.CustomerID
WHERE
tDealerships.DealershipName LIKE '%'+#Dealership+'%'
AND NOT tInternalLocations.LocationName = 'Down Deal'
AND tVehicleDeal.Titled IS NULL
AND tVehicleDeal.Archived = 0
GROUP BY
DealDate,
DateReceived,
Bounced,
StockNumber,
LocationName,
CustomerName;
I'm pulling my hair out over a subquery that I'm using to avoid about 100 duplicates (out of about 40k records). The records that are duplicated are showing up because they have 2 dates in h2.datecreated for a valid reason, so I can't just scrub the data.
I'm trying to get only the earliest date to return. The first subquery (that starts with "select distinct address_id", with the MIN) works fine on it's own...no duplicates are returned. So it would seem that the left join (or just plain join...I've tried that too) couldn't possibly see the second h2.datecreated, since it doesn't even show up in the subquery. But when I run the whole query, it's returning 2 values for some ipc.mfgid's, one with the h2.datecreated that I want, and the other one that I don't want.
I know it's got to be something really simple, or something that just isn't possible. It really seems like it should work! This is MSSQL. Thanks!
select distinct ipc.mfgid as IPC, h2.datecreated,
case when ad.Address is null
then ad.buildingname end as Address, cast(trace.name as varchar)
+ '-' + cast(trace.Number as varchar) as ONT,
c.ACCOUNT_Id,
case when h.datecreated is not null then h.datecreated
else h2.datecreated end as Install
from equipmentjoin as ipc
left join historyjoin as h on ipc.id = h.EQUIPMENT_Id
and h.type like 'add'
left join circuitjoin as c on ipc.ADDRESS_Id = c.ADDRESS_Id
and c.GRADE_Code like '%hpna%'
join (select distinct address_id, equipment_id,
min(datecreated) as datecreated, comment
from history where comment like 'MAC: 5%' group by equipment_id, address_id, comment)
as h2 on c.address_id = h2.address_id
left join (select car.id, infport.name, carport.number, car.PCIRCUITGROUP_Id
from circuit as car (NOLOCK)
join port as carport (NOLOCK) on car.id = carport.CIRCUIT_Id
and carport.name like 'lead%'
and car.GRADE_Id = 29
join circuit as inf (NOLOCK) on car.CCIRCUITGROUP_Id = inf.PCIRCUITGROUP_Id
join port as infport (NOLOCK) on inf.id = infport.CIRCUIT_Id
and infport.name like '%olt%' )
as trace on c.ccircuitgroup_id = trace.pcircuitgroup_id
join addressjoin as ad (NOLOCK) on ipc.address_id = ad.id
The typical approach to only getting the lowest row is one of the following. You didn't bother to specify what version of SQL Server you're using, what you want to do with ties, and I have little interest to try to work this into your complex query, so I'll show you an abstract simplification for different versions.
SQL Server 2000
SELECT x.grouping_column, x.min_column, x.other_columns ...
FROM dbo.foo AS x
INNER JOIN
(
SELECT grouping_column, min_column = MIN(min_column)
FROM dbo.foo GROUP BY grouping_column
) AS y
ON x.grouping_column = y.grouping_column
AND x.min_column = y.min_column;
SQL Server 2005+
;WITH x AS
(
SELECT grouping_column, min_column, other_columns,
rn = ROW_NUMBER() OVER (ORDER BY min_column)
FROM dbo.foo
)
SELECT grouping_column, min_column, other_columns
FROM x
WHERE rn = 1;
This subqery:
select distinct address_id, equipment_id,
min(datecreated) as datecreated, comment
from history where comment like 'MAC: 5%' group by equipment_id, address_id, comment
Probably will return multiple rows because the comment is not guaranteed to be the same.
Try this instead:
CROSS APPLY (
SELECT TOP 1 H2.DateCreated, H2.Comment -- H2.Equipment_id wasn't used
FROM History H2
WHERE
H2.Comment LIKE 'MAC: 5%'
AND C.Address_ID = H2.Address_ID
ORDER BY DateCreated
) H2
Switch that to OUTER APPLY in case you want rows that don't have a matching desired history entry.