There are 21 rows in the table. 7 are for year 2011, 7 are for 2012 and the remaining 7 are for 2013. I want to get the latest year's 7 rows.
SELECT S1, S2, S1 * S2 AS M
FROM BLGND
WHERE DID = #dID AND
PMID = #pmID AND
yearr IN (SELECT MAX(yearr) AS y FROM BLGND AS BLGND_1)
I successfully bring the latest year's rows with the query above in MS Visual Studio Environment. But When I run the query in an ASP.NET page It brings all 21 records.
In other words yearr IN (SELECT MAX(yearr) AS y FROM BLGND AS BLGND_1) makes no difference.
yearr column's type is int
What could be the problem? OR is there a better query you know?
You could simply write
SELECT S1, S2, S1 * S2 AS M
FROM BLGND
WHERE DID = #dID AND
PMID = #pmID AND
YEAR([fieldWithDate]) = #yearRequested
Where fieldWithDate is assumed to be a smalldatetime or datetime field from which you want to get the year value and #yearRequested is a parameter that you pass to your query from your code.
You could extract the year value using the YEAR(expression) T-SQL function
Of course, if the field to search for the year value is just an integer containing the year values of your rows the query is simpler
SELECT S1, S2, S1 * S2 AS M
FROM BLGND
WHERE DID = #dID AND
PMID = #pmID AND
fieldWithYearValue = #yearRequested
If you don't want to pass the parameter for the year, but just want to retrieve always the set of rows of the last year for a specific user then
SELECT S1, S2, S1 * S2 AS M
FROM BLGND
WHERE DID = #dID AND
PMID = #pmID AND
fieldWithYearValue = (SELECT MAX(fieldWithYearValue) FROM BLGND)
Related
We are working on PeopleSoft ELM 9.2 and I'm not finding what I need in any of the OOB queries so I'm attempting to build one. We need to get a "First Time Pass Rate" score, or the average of how many people pass a learning course on their first try. Ideally we would have the data for each attempt so that we could also see how many attempts a particular person or course has prior to getting a passing score.
Our setup includes SCORM 1.2 modules that pass off a score to the LMS for verification that a passing score was received. The closest I've been able to come so far is to get a "Pass/Fail" score but either my query unions are incorrect or the data is incorrect as it returns extraneous data that is not relevant to the other data returned or (if I force distinct values) it returns sporadically accurate data. Below is the SQL that I'm using if it helps.
Has anyone tried to build this kind of query before and how did you do it? :)
SELECT DISTINCT D1X.XLATLONGNAME, D.LM_ORGANIZATION_ID, D.LM_ORG_DESCR,
D.LM_HR_EMPLID, TO_CHAR(D.LM_HIRE_DT,'YYYY-MM-DD'), D.FIRST_NAME,
D.LAST_NAME, C.LM_CS_LONG_NM, C.LM_ACT_CD, A.LM_LC_LONG_NM, A.LM_LC_ID,
B12X.XLATLONGNAME, TO_CHAR(B.LM_COMPL_DT,'YYYY-MM-DD'), B.LM_ENRLMT_ID,
E15X.XLATLONGNAME
FROM PS_LM_LC A, PS_LM_ENRLMT B LEFT OUTER JOIN PSXLATITEM B12X ON
B12X.FIELDNAME='LM_STTS' AND B12X.FIELDVALUE=B.LM_STTS AND B12X.EFF_STATUS =
'A' AND B12X.EFFDT = (SELECT MAX(EFFDT) FROM PSXLATITEM TB WHERE
TB.FIELDNAME=B12X.FIELDNAME AND TB.FIELDVALUE=B12X.FIELDVALUE AND
TB.EFF_STATUS = 'A' AND TB.EFFDT <= TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-
DD'),'YYYY-MM-DD') ), PS_LM_ACT_CI_VW C, PS_LM_PERS_DTL_VW D LEFT OUTER JOIN
PSXLATITEM D1X ON D1X.FIELDNAME='LM_ACTIVE' AND D1X.FIELDVALUE=D.LM_ACTIVE
AND D1X.EFF_STATUS = 'A' AND D1X.EFFDT = (SELECT MAX(EFFDT) FROM PSXLATITEM
TB WHERE TB.FIELDNAME=D1X.FIELDNAME AND TB.FIELDVALUE=D1X.FIELDVALUE AND
TB.EFF_STATUS = 'A' AND TB.EFFDT <= TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-
DD'),'YYYY-MM-DD') ), PS_LM_ENR_LC_BL_VW E LEFT OUTER JOIN PSXLATITEM E15X
ON E15X.FIELDNAME='LM_PASS_STTS' AND E15X.FIELDVALUE=E.LM_PASS_STTS AND
E15X.EFF_STATUS = 'A' AND E15X.EFFDT = (SELECT MAX(EFFDT) FROM PSXLATITEM TB
WHERE TB.FIELDNAME=E15X.FIELDNAME AND TB.FIELDVALUE=E15X.FIELDVALUE AND
TB.EFF_STATUS = 'A' AND TB.EFFDT <= TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-
DD'),'YYYY-MM-DD') )
WHERE ( A.LM_ACT_ID = B.LM_ACT_ID
AND A.LM_ACT_ID = C.LM_ACT_ID
AND D.LM_PERSON_ID = B.LM_PERSON_ID
AND D.BUSINESS_UNIT IN ('00340','00235')
AND B.LM_ENRL_DT BETWEEN TO_DATE(:1,'YYYY-MM-DD') AND TO_DATE(:2,'YYYY-MM-DD')
AND D.LM_HR_EMPLID = :3
AND D.LM_ACTIVE = :4
AND B.LM_STTS = 'COMP'
AND A.LM_LC_ID = E.LM_LC_ID
AND E.LM_PASS_STTS IN ('FAIL','PASS'))
I have the following columns (FirstCol, SecondCol, ThirdCol) in a sqlite3 db file:
1 Inside 100
1 Outside 200
2 Inside 46
2 Outside 68
First column has type INT, second has type TEXT and third one has type INT.
For each FirstCol value (in this case just 1 and 2) i need to obtain the result of the value associated with Outside/Inside, which is to say 200/100 where FirstCol=1 and 68/46 where FirstCol=2.
I don't mind whether this is done with a single query or by creating a new table, i just need that result.
Thanks.
You have to look up the values from different rows with correlated subqueries:
SELECT FirstCol,
(SELECT ThirdCol
FROM MyTable
WHERE FirstCol = T.FirstCol
AND SecondCol = 'Outside'
) /
(SELECT ThirdCol
FROM MyTable
WHERE FirstCol = T.FirstCol
AND SecondCol = 'Inside'
) AS Result
FROM (SELECT DISTINCT FirstCol
FROM MyTable) AS T;
I have query that runs as part of a function which produces a one row table full of counts, and averages, and comma separated lists like this:
select
(select
count(*)
from vw_disp_details
where round = 2013
and rating = 1) applicants,
(select
count(*)
from vw_disp_details
where round = 2013
and rating = 1
and applied != 'yes') s_applicants,
(select
LISTAGG(discipline, ',')
WITHIN GROUP (ORDER BY discipline)
from (select discipline,
count(*) discipline_number
from vw_disp_details
where round = 2013
and rating = 1
group by discipline)) disciplines,
(select
LISTAGG(discipline_count, ',')
WITHIN GROUP (ORDER BY discipline)
from (select discipline,
count(*) discipline_count
from vw_disp_details
where round = 2013
and rating = 1
group by discipline)) disciplines_count,
(select
round(avg(util.getawardstocols(application_id,'1','AWARD_NAME')), 2)
from vw_disp_details
where round = 2013
and rating = 1) average_award_score,
(select
round(avg(age))
from vw_disp_details
where round = 2013
and rating = 1) average_age
from dual;
Except that instead of 6 main sub-queries there are 23.
This returns something like this (if it were a CSV):
applicants | s_applicants | disciplines | disciplines_count | average_award_score | average_age
107 | 67 | "speed,accuracy,strength" | 3 | 97 | 23
Now I am programmatically swapping out the "rating = 1" part of the where clauses for other expressions. They all work rather quickly except for the "rating = 1" one which takes about 90 seconds to run and that is because the rating column in the vw_disp_details view is itself compiled by a sub-query:
(SELECT score
FROM read r,
eval_criteria_lookup ecl
WHERE r.criteria_id = ecl.criteria_id
AND r.application_id = a.lgo_application_id
AND criteria_description = 'Overall Score'
AND type = 'ABC'
) reader_rank
So when the function runs this extra query seems to slow everything down dramatically.
My question is, is there a better (more efficient) way to run a query like this that is basically just a series of counts and averages, and how can I refactor to optimize the speed so that the rating = 1 query doesn't take 90 seconds to run.
You could choose to MATERIALIZE the vw_disp_details VIEW. That would pre-calculate the value of the rating column. There are various options for how up-to-date a materialized view is kept, you would probably want to use the ON COMMIT clause so that vw_disp_details is always correct.
Have a look at the official documentation and see if that would work for you.
http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_6002.htm
Do all most of your queries in only one. Instead of doing:
select
(select (count(*) from my_tab) as count_all,
(select avg(age) from my_tab) as avg_age,
(select avg(mypkg.get_award(application_id) from my_tab) as_avg-app_id
from dual;
Just do:
select count(*), avg(age),avg(mypkg.get_award(application_id)) from my_tab;
And then, maybe you can do some union all for the other results. But this step all by itself should help.
I was able to solve this issue by doing two things: creating a new view that displayed only the results I needed, which gave me marginal gains in speed, and in that view moving the where clause of the sub-query that caused the lag into the where clause of the view and tacking on the result of the sub-query as column in the view. This still returns the same results thanks to the fact that there are always going to be records in the table the sub-query accessed for each row of the view query.
SELECT
a.application_id,
util.getstatus (a.application_id) status,
(SELECT score
FROM applicant_read ar,
eval_criteria_lookup ecl
WHERE ar.criteria_id = ecl.criteria_id
AND ar.application_id = a.application_id
AND criteria_description = 'Overall Score' //THESE TWO FIELDS
AND type = 'ABC' //ARE CRITERIA_ID = 15
) score
as.test_total test_total
FROM application a,
applicant_scores as
WHERE a.application_id = as.application_id(+);
Became
SELECT
a.application_id,
util.getstatus (a.application_id) status,
ar.score,
as.test_total test_total
FROM application a,
applicant_scores as,
applicant_read ar
WHERE a.application_id = as.application_id(+)
AND ar.application_id = a.application_id(+)
AND ar.criteria_id = 15;
I have two tables(oracle):
(I have marked the primary keys with a star before the column name)
Table1 Columns are :
*date,
*code,
*symbol,
price,
weight
Table2 columns are :
*descriptionID
code
symbol
date
description
I need to find the below information using query,
For a given code and a symbol on a particular day,is there any description.
for example: code = "AA" and symbol = "TEST" on 2012-4-1 on Table 1 => is there atleast one row like ID=, code ="AA", symbol ="TEST" ,date = 2012-4-1 in table 2
I tried with the below query:
select * from Table1 t1 INNER JOIN
Table2 t2
on t1.code = t2.code and t1.symbol = t2.symbol and
TO_CHAR(t1.date, 'YYYY/MM/DD') = TO_CHAR(t1.date, 'YYYY/MM/DD')
But it doesnt give me output like:
code = AA, symbol = TEST, date 2012-4-1 => descrition count = 10
code = AA, symbol = TEST, date 2012-4-2 => descrition count = 5
code = BB, symbol = HELO, date 2012-4-1 => descrition count = 20
Can some one suggest me a query which can achieve the above output.
I don't see why you need the join:
SELECT count(*)
FROM Table2
WHERE code='AA'
AND symbol = 'TEST'
AND date = to_date('2012-04-01', 'yyyy-mm-dd')
UPDATE: (after reading your comment)
I still don't see why you need the join. Do you need some data from table1 ?
Anyway, if you want the count for all the (code,symbol,date)s then why not group by ?
As for the dates, better use trunc to get rid of the time parts.
So:
SELECT code, symbol, date, count(*)
FROM Table2
GROUP BY code, symbol, date
the Trunc() Method takes a String\Date input and Creates a DATE output that is in this Format: "DD\MM\YYYY".
So Its should do exactly what you want.
I need some help to build SQL Query. I have table having data like:
ID Date Name
1 1/1/2009 a
2 1/2/2009 b
3 1/3/2009 c
I need to get result something like...
1 1/1/2009 a
2 1/2/2009 b
3 1/3/2009 c
4 1/4/2009 Null
5 1/5/2009 Null
6 1/6/2009 Null
7 1/7/2009 Null
8 1/8/2009 Null
............................
............................
............................
30 1/30/2009 Null
31 1/31/2009 Null
I want query something like..
Select * from tbl **where month(Date)=1 AND year(Date)=2010**
Above is not completed query.
I need to get all the record of particular month, even if some date missing..
I guess there must be equi Join in the query, I am trying to build this query using Equi join
Thanks
BIG EDIT
Now understand the OPs question.
Use a common table expression and a left join to get this effect.
DECLARE #FirstDay DATETIME;
-- Set start time
SELECT #FirstDay = '2009-01-01';
WITH Days AS
(
SELECT #FirstDay as CalendarDay
UNION ALL
SELECT DATEADD(d, 1, CalendarDay) as CalendarDay
FROM Days
WHERE DATEADD(d, 1, CalendarDay) < DATEADD(m, 1, #FirstDay)
)
SELECT DATEPART(d,d.CalendarDay), **t.date should be (d.CalendarDay)**, t.Name FROM Days d
LEFT JOIN tbl t
ON
d.CalendarDay = t.Date
ORDER BY
d.CalendarDay;
Left this original answer at bottom
You need DATEPART, sir.
SELECT * FROM tbl WHERE DATEPART(m,Date) = 1
If you want to choose month and year, then you can use DATEPART twice or go for a range.
SELECT * FROM tbl WHERE DATEPART(m,Date) = 1 AND DATEPART(yyyy,Date) = 2009
Range :-
SELECT * FROM tbl WHERE Date >= '2009-01-01' AND Date < '2009-02-01'
See this link for more info on DATEPART.
http://msdn.microsoft.com/en-us/library/ms174420.aspx
You can use less or equal to.
Like so:
select * from tbl where date > '2009-01-01' and date < '2009-02-01'
However, it is unclear if you want month 1 from all years?
You can check more examples and functions on "Date and Time Functions" from MSDN
Create a temporary table containing all days of that certain month,
Do left outer join between that table and your data table on tempTable.month = #month.
now you have a big table with all days of the desired month and all the records matching the proper dates + empty records for those dates who have no data.
i hope that's what you want.