Im trying to write a query that will list the Consultant_Id, Name and age for all consultants who have a Grade of 'D' in my Consultant table, and were born more than 30 years ago and have a name that begins with the letter 'L'. I need the output ascending age order. so far i have this but i presume there is multiple errors, any help would be greatly appreciated!
I don't want to seem to be attacking you, but since you said you've been trying to figure this out for a long time and you're stuck, let's look at some of the problems with what you have at the moment.
SELECT Consultant_Id, Name, DOB,
This line has a trailing comma.
FROM Consultant;
This line has a semicolon at the end, terminating the statement, so your where clause is a separate invalid command.
WHERE DOB = (SELECT MAX(DOB <= 01-jan-85) FROM CONSULTANT)
You seem to be using 01-jan-85 as a date, but even if it was in single quotes it would be a string not a date and you should explicitly convert it to a date type; without quotes it would get an invalid identifier (trying to treat 'jan' as a column name). Using the <= comparator inside a max() call isn't valid anyway, and I'm not quite sure what it's supposed to achieve. At best you're getting the most recent DOB from the table in the subquery, and then using that to filter the main query so you will only get the row (or maybe rows) that match that exact date. It won't give you all DOBs more than 30 years ago.
WHERE name( SELECT SUBSTR(Name,1,20) LIKE 'L%' AS ShortName)
name() isn't a function, so perhaps you meant to compare it with =; but as with the DOB check that isn't really what you wan. Your subquery doesn't have a from clause, and isn't correlated with the main query so would return multiple rows, which is an error in itself. As this is the second filter you should be using AND rather than a second WHERE. And the substr() isn't really adding anything since you're using like anyway.
WHERE Grade = 'D'
This is almost OK, but should also be AND not `WHERE.
ORDER BY SUBSTR(DOB, 7,9);
This is doing an implicit conversion of DOB to a string, then getting characters 7 to 15 of whatever your session converts it to by default. Based on the date string you used earlier you means substr(dob, 7, 2), which would give you the 2-digit year in that format; but you're supposed to be ordering by the whole DOB, not just the year.
#HepC has given the actual command you need (aside from the trailing comma on the first line).
I believe this is what you're looking for.
SELECT consultant_id, name, DOB
FROM consultant
WHERE DOB <= ADD_MONTHS((SYSDATE), -360)
AND grade = 'D'
AND name LIKE 'L%'
ORDER BY DOB;
SELECT consultant_id, name, DOB
FROM consultant
WHERE DOB <= ADD_MONTHS(TRUNC(SYSDATE), 12 * -30)
AND name LIKE 'L%'
AND grade = 'D'
ORDER BY DOB;
SELECT Consultant_Id, Name AS ShortName, DOB
FROM Consultant
WHERE DOB < dateadd(year, -30, getdate())
AND name LIKE 'L%'
AND Grade = 'D'
ORDER BY DOB
Related
There is a Table with a age-column. The Value of this column is a varchar because the age of persons under the age of 1 is saved in months with an additional 'm' (9 Month old -> '9m')
I know that this is generally a bad idea and one should rather persist the date of birth, but in this case the age refers to the age on a specific day in history - and additionally this is part of a lesson and the whole point is learning how to treat "weird" data.
My first idea was to put a leading zero on all ages which are not purely numeric:
SELECT *
FROM db
ORDER BY REPLACE(age, (IF ISNUMERIC(age) age ELSE CONCAT('0', age))) DESC;
However this is not a valid SQL-statement and neither are my other attempts.
The question is: How can I adjust the value used for ORDER BY without altering the db?
Another approach would be to select only the rows with a purely numeric age value and a separate select for the remaining rows order both of them separately and combine them afterwards.
My take on this was the following:
(SELECT name, age
FROM titanic
WHERE ISNUMERIC(age)
ORDER BY age DESC)
UNION
(SELECT name, age
FROM titanic
WHERE NOT ISNUMERIC(age)
ORDER BY age);
This is in fact valid or at least it gives me a result. But in the result I can't really see what happened to the order, it looks like the UNION undos everything.
Thanks in advance, will take any tip or even just the name of the function/method I should look into!
Would this work?
SELECT name, age
FROM titanic
ORDER BY isnumeric(age), age
I would use "Case When" structure with some transformations in the "Order by" to get the total number of months for both types of ages.
Select name, age
From tbl
Where age SIMILAR TO '[1-9][0-9]*' Or
age SIMILAR TO '[1-9][0-2]?m'
Order by Case When age SIMILAR TO '[1-9][0-2]?m' Then Substring(age,1,CHAR_LENGTH(age)-1)::int
When age SIMILAR TO '[1-9][0-9]*' Then age::int * 12 End
First off storing age is a poor idea, you must update every row regularly, in this case at least monthly. Storing it as string turns a poor idea into a terrible idea. Not only do you have the maintenance, it is not straight forward nor is it straight forward to insert it. Instead store date-of-birth as a timestamp or date. You can then quickly get age (via the age) you can then use the extract function on the resulting interval at whatever level is desired. If you absolutely must present age with text indicator for either years/months (or even days) you create a view that derives the appropriate value. (see demo)
create or replace view titanic as
select name "Name"
, case when extract( year from age(dob))::integer > 0 then to_char (extract( year from age(dob)), '999') || ' years'
when extract( month from age(dob))::integer> 0 then to_char (extract( month from age(dob)), '99') || ' months'
else to_char (extract( day from age(dob)),'99') || ' days'
end "Age"
from titanic_tbl;
I am trying to use columns that I created in this query to create another column.
Let me first my messy query. The query looks like this:
SELECT tb.team, tb.player, tb.type, tb.date, ToChar(Current Date-1, 'DD-MON-YY') as yesterday,
CASE WHEN to_date(tb.date) = yesterday then 1 else 0 end dateindicator,
FROM (
COUNT DISTINCT(*)
FROM TABLE_A, dual
where dateindicator = 1
Group by tb.team
)
What I am trying to do here is:
creating a column with "Yesterday's date"
Using the "Yesterday" column to create another column called dateindicator indicating each row is yesterday's data or not.
then using that dateindicator, I want to count the distinct number of player for each team that has 1 of the dateindicator column.
But I am getting the "invalid identifier" error. I am new to this oracle SQL, and trying to learn here.
You cannot use an Alias in your Select statement.
see here: SQL: Alias Column Name for Use in CASE Statement
you need to use the full toChar(.. in the CASE WHEN.
Also:
Your WHERE-condition (Line 5) doesnt belong there.. it should be:
SELECT DISTINCT .>. FROM .>. WHERE. you have to specify the table first. then you can filter it with where.
If I follow your explanation correctly: for each team, you want to count the number of players whose date column is yesterday.
If so, you can just filter and aggregate:
select team, count(*) as cnt
from mytable
where mydate >= trunc(sysdate) - 1 and mydate < trunc(sysdate)
group by team
This assumes that the dates are stored in column mydate, that is of date datatype.
I am unsure what you mean by counting distinct players; presumably, a given player appears just once per team, so I used count(*). If you really need to, you can change that to count(distinct player).
Finally: if you want to allow teams where no player matches, you can move the filtering logic within the aggregate function:
select team,
sum(case when mydate >= trunc(sysdate) - 1 and mydate < trunc(sysdate) then 1 else 0 end) as cnt
from mytable
group by team
If anyone could help me with the following, I'd be grateful:
I'm trying to write a code (create an alert in PowerSchool) that will indicate if a student is younger or older than average for their current grade level. (For example, as student born before 6/30/2002 is older than average for 9th grade) I can't seem to make DECODE work in conjunction with >= TO_DATE. Here's my statement:
select lastfirst, decode (dob >= to_date ('2002-06-30', 'yyyy-mm-dd'), 'old') DOB
from students
where grade_level = 9
order by lastfirst
You probably could get away with using a PowerSchool decode in your sql, but I find code easier to write when fewer languages/systems are included, so I would leave it out. I would also let SQL do the average age calculation so you don't have to supply or calculate average dates yourself (see Averaging dates in oracle sql for an explanation of the TO_DATE line).
SELECT
LastFirst AS "Student Name"
,CASE WHEN dob >= (
SELECT
TO_DATE(ROUND(AVG(TO_NUMBER(TO_CHAR(dob, 'J')))),'J')
FROM Students
WHERE Grade_Level = 9
AND Enroll_Status = 0
) THEN 'Younger' ELSE 'Older' END AS "Older or Younger?"
FROM Students
WHERE Grade_Level = 9
ORDER BY LastFirst
The subquery calculates the average birthday, and the CASE statement compares each of your records against that, reporting if it's older or younger.
In the subquery that calculates the average, I've taken the liberty of assuming you only want to compare against currently enrolled students, since withdrawn students retain the same grade level. You don't really want those students who left 10 years ago and are still listed as a 9th grader to mess with your average numbers.
I am VERY new to any language. In sql, I'm trying to find the avg of data using the datediff function to compute the age. I know the ages, but I simply have no clue as how to write the statement.
when I run this statement, I get the information I'm looking for. However, I also need to use the datediff function to compute the age from the DOB. This is where I get lost. Here is what I have, and I get an error when I run it.
select firstname,lastname, dob
SELECT DATEDIFF(day,'1970-01-01','1978-05-27') AS DiffDate
where occupationId = 164 and gender = 'M';
Again, I new to this and have researched for and answer and to get understanding. I need help.
You've got a few issues with your SQL query.
MySQL DATEDIFF does not have an interval parameter i.e. day. It only takes two datetime parameters. During your research, you must've come across SQL Server documentation.
Use TIMESTAMPDIFF instead (which takes an interval) like so TIMESTAMPDIFF(year, dob, CURDATE()) AS currentage which gets you their current age.
No FROM clause and table is specified, so where are you getting firstname, lastname, dob, occupationId and gender from?
You do not need a sub select query to calculate the age.
The revised query for you (you'll need to specify the table name where you're getting your data from):
SELECT firstname, lastname, dob, TIMESTAMPDIFF(year, dob, CURDATE()) AS currentage
FROM tableName
WHERE occupationId = 164 and gender = 'M';
`
Im new to stack so please go easy on me. Ive looked all over the web and cant find anything that really helps me.
So I need to provide details of all regular academics working in the Computing Department who were
over 60 years old as of 31/12/2014.
my trouble comes with how would I approach showing data of someone 60+ could you minus one date from another date? or is there is possible sql command that I am missing.
my attempt:
SELECT *
FROM staff, department
WHERE DOB <= '31/12/1964'
AND staff.department_ID = department.department _ID
There are functions to calculate the difference between dates, but the most efficient is to first calculate the date that a person would be born to be 60 at 2014-12-31. That way you make a direct comparison to a value, so the database can make use of an index if there is one.
Example for Oracle:
select
PersonId, FirstName, LastName
from
Person
where
Born <= add_months(date '2014-12-31', -60 * 12)
Example for MySQL (eventhough you removed the MySQL tag):
select
PersonId, FirstName, LastName
from
Person
where
Born <= date_sub('2014-12-31' 60 year)
I think In SQL SERVER
Select Datediff(DAYS,'05-19-2015','05-21-2015')
In My SQL
SELECT TIMESTAMPDIFF(HOUR, start_time, end_time)
as difference FROM timeattendance WHERE timeattendance_id = '1484'
The oracle add_months function will help you.
where yourfield < add_months(date '1964-12-31', 60*12 )