I'm after some ideas on how I can write some Oracle SQL code to show a different field value depending on what the job_type_code is.
If the job_type_code is either EN11 or EN12 the only jobs that need to be returned are those where the target_comp_date is in the past.
If the job_type_code is either EN90 or EN91 all jobs should be displayed with the target_comp_date.
Code I've tried putting in is below.
select
case
when job_type.job_type_code in ('EN11','EN12') and job.target_comp_date < SYSDATE then
job.target_comp_date
when job_type.job_type_code in ('EN90','EN91') then job.target_comp_date
else 'check'
end as Test
from
job
inner join job_type on job.job_type_key = job_type.job_type_key
I think you need a WHERE clause here, not a CASE expression:
SELECT *
FROM job j
INNER JOIN job_type jt
ON j.job_type_key = jt.job_type_key
WHERE
(jt.job_type_code IN ('EN11', 'EN12') AND j.target_comp_date < SYSDATE) OR
jt.job_type_code IN ('EN90', 'EN91');
A case expression in the select is not going to filter any data. This sounds like a where clause:
where (job_type_code in ('EN11', 'EN12') and target_comp_date < sysdate
) or
(job_type_code in ('EN90', 'EN91') and target_comp_date > sysdate
)
It is not clear if you want other job_type_codes. If so, add or (job_type_code not in ('EN11', 'EN12', 'EN90', 'EN91').
Related
Pretty sure it's a simple fix, but I'm lost. Trying to pull data from joined tables where there's a checkbox = 1 (gditwocertflag). I only want to see the specific row that's checked. But I'm pulling every labor row from work orders that meet specificed criteria with that block being checked. I've tried to join different ways with the same result, so I'm pretty sure it's not the join that's the issue. Also tried a nested select that errored on the sub query returning more than 1 row. Here's where I'm at right now. Is it how I'm calling it?
select w.wonum, l.laborcode as certifier
from maximo.workorder W, maximo.labtrans L
where w.wonum = l.refwo
and w.status = 'CLOSE'
and w.gditperformingrcc like ('MDKM%')
and w.gditusertype = 'PMEL'
and w.wonum not like ('QA%')
and l.gditwocertflag = '1'
and parent is null
and (w.actfinish >= trunc(add_months(sysdate, -12), 'MM')
and w.actfinish < trunc(add_months(sysdate, -0), 'MM'))
;
Thanks for your help. Problem solved. We share a database with two other locations and I didn't filter them out specifically. I thought the filters I had would have done the trick. However, it didn't. And coincidentally they have the some work order numbers that match some of ours, which isn't supposed to happen. Which is why it appeared I was returning incorrect data. I've been scratching my head at this for the last two days...
If GDITWOCERTFLAG is a YORN field in Maximo you should be using an Integer value to compare:
select w.wonum, l.laborcode as certifier
from maximo.workorder W
join maximo.labtrans L
on w.wonum = l.refwo
and l.gditwocertflag = 1
where w.status = 'CLOSE'
and w.gditperformingrcc like ('MDKM%')
and w.gditusertype = 'PMEL'
and w.wonum not like ('QA%')
and parent is null
and (w.actfinish >= trunc(add_months(sysdate, -12), 'MM')
and w.actfinish < trunc(add_months(sysdate, -0), 'MM'))
;
I have 2 tables:
tblAbsence
Name Start End Status
John 4/2/18 4/5/18 Approved
Sue 5/1/18 5/10/18 Denied
tblManning
Date Required
4/1/18 3
4/2/18 4
4/3/18 2
I would like to be able to update tblAbsence.Status to "Approved" as long as the Required value during the absence request doesn't exceed an arbitrary limit (4 for example).
After looking at #Jeffrey's proposal and experimenting I think I need an Update query which Sets [Status]= Approved when leave request is not found in query below. The below query will tell me if a request has any days that exceed the Limit.
SELECT tblAbsence.name, tblAbsence.start, tblAbsence.end
FROM tblAbsence, tblManning
WHERE tblManning.Date >= Int([tblAbsence].[Start]) And tblManning.Date <= [tblAbsence].[End] AND tblManning.[Req]>3
GROUP BY tblAbsence.name, tblAbsence.[Start], tblAbsence.end;
I renamed the above query as qryLv and tried this Left Join but it tells me I must use an updatable query????
Update tblAbsence a
Left Join qryLv L
ON L.name = a.name AND l.start = a.start
SET a.Status = "Approved"
WHERE l.name is null;
Your error is showing because you have to either equate or use IN/EXISTS with a variable when using subqueries in WHERE clauses. However, I'm not sure you need a subquery, I think something like this will work:
UPDATE tblAbsence SET tblAbsence.Status = "Approved"
FROM tblAbsence, tblManning
WHERE tblManning.Date > tblAbsence.Start
AND tblManning.Date <= tblAbsence.End + #23:59:59#
AND tblManning.Required < 4;
Ok, kinda missed that part, you will need a subquery. I think you need to use NOT EXISTS just to check if your subquery returns any values or not and that should work for you.
UPDATE tblAbsence SET tblAbsence.Status = "Approved"
FROM tblAbsence
WHERE NOT EXISTS (
SELECT NULL
FROM tblManning
WHERE tblManning.Date > tblAbsence.Start
AND tblManning.Date <= tblAbsence.End + #23:59:59#
AND tblManning.Required < 4);
I think you can use NULL in the subquery since you are not returning records, just a boolean, but if it doesn't work you can replace it with *.
So, I'm trying to run a SQL Statement to select and entire DB for upload in an ETL process, but I want to create a calculated column for the number of days between a ticket opening and being closed.
The IF-THEN logic is like this:
IF the department is Grounds Maintenance, and there's a foreign key match with a second table, and there's specific task type, then use formula A
ELSE
IF INCIDENT_RESOLVED_DATE IS NULL, then use formula B
ELSE use formula C
I think my CASE logic is solid, but it keeps bringing me back the same row over and over again. This tells me I'm missing something. I'm almost positive it's something to do with the WHEN statement on the first part of the CASE statement, but if I knew, I wouldn't be asking.
SELECT
a.*
, a.REPORTED_DATE
, a.CLOSE_DATE
, a.INCIDENT_RESOLVED_DATE
, CASE
WHEN DEPARTMENT = 'Grounds Maintenance'
AND a.INCIDENT_ID = b.SOURCE_OBJECT_ID
AND b.TASK_TYPE_ID = '11501'
THEN (to_date(b.ACTUAL_END_DATE, 'DD-MM-YYYY') - to_date(a.REPORTED_DATE, 'DD-MM-YYYY'))
ELSE CASE
WHEN a.INCIDENT_RESOLVED_DATE IS NULL THEN (to_date(a.CLOSE_DATE, 'DD-MM-YYYY') - to_date(a.REPORTED_DATE, 'DD-MM-YYYY'))
ELSE (to_date(a.INCIDENT_RESOLVED_DATE, 'DD-MM-YYYY') - to_date(a.REPORTED_DATE, 'DD-MM-YYYY'))END
END
AS
DAYS_TO_RESOLVE
FROM
CMEM_CS_SERVICE_REQUESTS a, jtf_tasks_b b
WHERE
EXTRACT(YEAR FROM a.REPORTED_DATE) > 2009;
Thoughts?
This source is good but too slow.
Function:
Selecting all rows if SC and %%5 and 2013.07.11 < date < 2013.07.18
and
some older lines represent lines
Method:
Finding X count rows.
one by one to see whether there is consistency 28 days
select efi_name, efi_id, count(*) as dupes, id, mlap_date
from address m
where
mlap_date > "2013.07.11"
and mlap_date < "2013.07.18"
and mlap_type = "SC"
and calendar_id not like "%%5"
and concat(efi_id,irsz,ucase(city), ucase(address)) in (
select concat(k.efi_id,k.irsz,ucase(k.city), ucase(k.address)) as dupe
from address k
where k.mlap_date > adddate(m.`mlap_date`,-28)
and k.mlap_date < m.mlap_date
and k.mlap_type = "SC"
and k.calendar_id not like "%%5"
and k.status = 'Befejezett'
group by concat(k.efi_id,k.irsz,ucase(k.city), ucase(k.address))
having (count(*) > 1)
)
group by concat(efi_id,irsz,ucase(city), ucase(address))
Thanks for helping!
NOT LIKE plus wildcard-prefixed terms are index-usage killers.
You could also try replacing the IN + inline table with an inner join: does the optimizer run the NOT LIKE query twice (see your explain plan)?
It looks like you might be using MySql, in which case you could build a hash column based on
efi_id
irsz
ucase(city)
ucase(address))
and compare that column directly. This is a way of implementing a hash join in MySql.
I don't think you need a subquery to do this. You should be able to do it just with the outer group by and conditional aggregations.
select efi_name, efi_id,
sum(case when mlap_date > "2013.07.11" and mlap_date < "2013.07.18" then 1 else 0 end) as dupes,
id, mlap_date
from address m
where mlap_type = 'SC' and calendar_id not like '%%5'
group by efi_id,irsz, ucase(city), ucase(address)
having sum(case when m.status = 'Befejezett' and
m.mlap_date <= '2013.07.11' and
k.mlap_date > adddate(date('2013.07.11'), -28)
then 1
else 0
end) > 1
This produces a slightly different result from your query. Instead of looking at the 28 days before each record, it looks at all records in the week period and then at the four weeks before that period. Despite this subtle difference, it is still identifying dupes in the four-week period before the one-week period.
So I decided to try out PostgreSQL instead of MySQL but I am having some slight conversion problems. This was a query of mine that samples data from four tables and spit them out all in on result.
I am at a loss of how to convey this in PostgreSQL and specifically in Django but I am leaving that for another quesiton so bonus points if you can Django-fy it but no worries if you just pure SQL it.
SELECT links.id, links.created, links.url, links.title, user.username, category.title, SUM(votes.karma_delta) AS karma, SUM(IF(votes.user_id = 1, votes.karma_delta, 0)) AS user_vote
FROM links
LEFT OUTER JOIN `users` `user` ON (`links`.`user_id`=`user`.`id`)
LEFT OUTER JOIN `categories` `category` ON (`links`.`category_id`=`category`.`id`)
LEFT OUTER JOIN `votes` `votes` ON (`votes`.`link_id`=`links`.`id`)
WHERE (links.id = votes.link_id)
GROUP BY votes.link_id
ORDER BY (SUM(votes.karma_delta) - 1) / POW((TIMESTAMPDIFF(HOUR, links.created, NOW()) + 2), 1.5) DESC
LIMIT 20
The IF in the select was where my first troubles began. Seems it's an IF true/false THEN stuff ELSE other stuff END IF yet I can't get the syntax right. I tried to use Navicat's SQL builder but it constantly wanted me to place everything I had selected into the GROUP BY and that I think it all kinds of wrong.
What I am looking for in summary is to make this MySQL query work in PostreSQL. Thank you.
Current Progress
Just want to thank everybody for their help. This is what I have so far:
SELECT links_link.id, links_link.created, links_link.url, links_link.title, links_category.title, SUM(links_vote.karma_delta) AS karma, SUM(CASE WHEN links_vote.user_id = 1 THEN links_vote.karma_delta ELSE 0 END) AS user_vote
FROM links_link
LEFT OUTER JOIN auth_user ON (links_link.user_id = auth_user.id)
LEFT OUTER JOIN links_category ON (links_link.category_id = links_category.id)
LEFT OUTER JOIN links_vote ON (links_vote.link_id = links_link.id)
WHERE (links_link.id = links_vote.link_id)
GROUP BY links_link.id, links_link.created, links_link.url, links_link.title, links_category.title
ORDER BY links_link.created DESC
LIMIT 20
I had to make some table name changes and I am still working on my ORDER BY so till then we're just gonna cop out. Thanks again!
Have a look at this link GROUP BY
When GROUP BY is present, it is not
valid for the SELECT list expressions
to refer to ungrouped columns except
within aggregate functions, since
there would be more than one possible
value to return for an ungrouped
column.
You need to include all the select columns in the group by that are not part of the aggregate functions.
A few things:
Drop the backticks
Use a CASE statement instead of IF() CASE WHEN votes.use_id = 1 THEN votes.karma_delta ELSE 0 END
Change your timestampdiff to DATE_TRUNC('hour', now()) - DATE_TRUNC('hour', links.created) (you will need to then count the number of hours in the resulting interval. It would be much easier to compare timestamps)
Fix your GROUP BY and ORDER BY
Try to replace the IF with a case;
SUM(CASE WHEN votes.user_id = 1 THEN votes.karma_delta ELSE 0 END)
You also have to explicitly name every column or calculated column you use in the GROUP BY clause.