I am new to Oracle DBMS and I want to try the following:
I have an entity "Flight" with an attribute "DepartureTime", I want to know the number of flights at 2 different times and compare the count, then print which time has more flights
My attempt:
IF (SELECT COUNT(DepartureTime)
From Flight
WHERE DepartureTime='23:58')>
(SELECT COUNT(DepartureTime)
From Flight
WHERE DepartureTime='23:00')
BEGIN
PRINT 'First is bigger'
END
ELSE
BEGIN
PRINT 'Second is bigger'
END;
I am getting "Invalid SQL Statement"
Any help would be appreciated.
You can try this -
SELECT case when subq1.cnt > subq2.cnt then 'First is bigger' else 'Second is bigger' end as output
FROM
(SELECT COUNT(DepartureTime) cnt From Flight WHERE DepartureTime='23:58') subq1,
(SELECT COUNT(DepartureTime) cnt From Flight WHERE DepartureTime='23:00') subq2;
I created two subqueries to count departure times and then compared those counts in outer query using case-when.
Its not the most efficient but it will meet your requirement.
Related
Find Melbourne VIP level 4 customers’ first name, last name who have hired the vehicle model as “Ranger ” at least 2 times in database. You write three different queries: one is using operator EXISTS and the other one is using operator IN. The third query with the main filter criteria in FROM clause of the main query or filter criteria in the sub-query. Find one with the better performance.
I Have tried this query;
SELECT c_fname, c_fname FROM rental WHERE
EXISTS(SELECT c_id FROM customer WHERE c_city = 'Melbourne' AND customer.vip_level = '4')
AND EXISTS (SELECT vehicle_reg FROM vehicle WHERE v_model = 'Ranger')
HAVING COUNT(c_id)>=2 GROUP BY c_lname, c_fname;
I am getting error: SQL Error: ORA-00934: group function is not allowed here
00934. 00000 - "group function is not allowed here"
can anyone help me with this question. really struggled to get this done?
You are selecting from the wrong subject table as Rental does not have c_fname or c_lname columns.
You want to "Find Melbourne VIP level 4 customers’ first name, last name" which would be in the customer table:
SELECT c_fname,
c_lname
FROM customer
WHERE c_city = 'Melbourne'
AND vip_level = 4;
Then you want to add an additional filter "who have hired the vehicle model as “Ranger ” at least 2 times in database". That requires you to use EXISTS (for the answer for the first query) and you need to correlate between the outer-query and the sub-query; once you have done that then you do not need a GROUP BY clause and you are aggregating over the entire result set of the sub-query and can just use a HAVING clause.
SELECT c_fname,
c_lname
FROM customer c
WHERE c_city = 'Melbourne'
AND vip_level = 4
AND EXISTS(
SELECT 1
FROM rental r
INNER JOIN vehicle v
ON (r.vehicle_reg = v.vehicle_reg)
WHERE c.c_id = r.c_id
AND v.v_model = 'Ranger'
HAVING COUNT(*) >= 2
);
Then you need to write the same query using IN instead of EXISTS and the same query a third time using JOIN conditions instead of IN or EXISTS and, finally, you need to compare the performance of all three queries.
I am stuck in a difficult situation. I need to compare the counts of 2 and update one of the tables based on the comparison. Below are the details:
I have 2 tables: dwh_idh_to_iva_metadata_t and lnd_sml_price_t.
Every day there is a package running that loads data from source table dwh_sml_price_t to destination table lnd_sml_price_t. This package also checks the counts between the tables "dwh_idh_to_iva_metadata_t" and "lnd_sml_price_t". If the counts are matching then it updates few columns in the table dwh_idh_to_iva_metadata_t and if the counts are not matching then the package throws an exception and exits. To do the count comparison we created a cursor and then fetching that cursor for comparison. The code for cursor is as follows:
CURSOR C_CNT_PRICE IS
SELECT
lnd.smp_batchrun_id batch_id,
lnd.lnd_count,
dwh.dwh_count
FROM
(
SELECT
smp_batchrun_id,
COUNT(*) lnd_count
FROM
iva_landing.lnd_sml_price_t
GROUP BY
smp_batchrun_id
) lnd
LEFT JOIN (
SELECT
batchrun_id,
sent_records_count dwh_count,
dwh_sending_table
FROM
dwh.dwh_idh_to_iva_metadata_t
) dwh ON dwh.batchrun_id = lnd.smp_batchrun_id
WHERE
dwh.dwh_sending_table = 'DWH_SML_PRICE_T'
ORDER BY
1 DESC; `
And the actual code for comparison is:
` FOR L_COUNT IN C_CNT_PRICE LOOP --0001,0002
IF L_COUNT.lnd_count = L_COUNT.dwh_count THEN
UPDATE DWH.DWH_IDH_TO_IVA_METADATA_T idh
SET idh.IVA_RECEIVING_TABLE = 'LND_SML_PRICE_T',
idh.RECEIVED_DATE = SYSDATE,
idh.RECEIVED_RECORDS_COUNT = L_COUNT.lnd_count,
idh.status = 'Verified'
WHERE L_COUNT.batch_id = idh.batchrun_id
AND idh.dwh_sending_table = 'DWH_SML_PRICE_T';
COMMIT;
ELSE
RAISE EXCPT_MISSDATA; -- Throw error and exit process immediately
END IF;
END LOOP; `
Now, the problem is that there may be certain cases when the table "LND_SML_PRICE_T" is not having any data, in which case, DWH_IDH_TO_IVA_METDATA_T should have the columns updated as in case of matching counts.
I need help in modifying the code so that comparison is done even in case of no records in LND_SML_PRICE_T table.
Thanks!
If there are no rows in LND_SML_PRICE_T table, cursor C_CNT_PRICE's LND_COUNT equals 0 which means that comparison code should be modified to
FOR L_COUNT IN C_CNT_PRICE LOOP
IF (L_COUNT.lnd_count = L_COUNT.dwh_count)
or L_COUNT.lnd_count = 0 --> this
THEN
I have a table attendance having columns
date1 ,status(either PRESENT or ABSENT),student_idstudent and student_subject_subjectid
I want make a query for student_idstudent and percentage attendance they have ie(count of present/total count) for each student for a particular subject.
Essentially I just want the values of two counts. Is there any easy way to do so without using views and preferably using pl/sql?
Below is my try using cursor.
Please tell me whether using the below code is it guaranteed to give corresponding answers(ie present count and total count) for each student_idstudent
Also tell me if this can fail in any other case?
DECLARE
s_id attendance.student_idstudent%type;
s_present number(3);
CURSOR student_present is select student_idstudent, count(student_idstudent) from attendance
where status like 'Present' and student_subject_subjectid like 102
group by student_idstudent;
s1_id attendence.student_idstudent%type;
s1_total number(3);
CURSOR student_total is select student_idstudent, count(student_idstudent) from attendance
where student_subject_subjectid like 102
group by student_idstudent;
BEGIN
OPEN student_present;
OPEN student_total;
LOOP
FETCH student_present into s_id, s_present;
FETCH student_total into s1_id, s1_total;
EXIT WHEN student_present%notfound;
dbms_output.put_line('student '|| s_id || ' has ' ||S_present/s1_total*100 || '% record' );
END LOOP;
CLOSE student_present;
CLOSE student_total;
END;
/
I'm not sure if this is a homework question or not, so Im giving you a partial answer, and you should be able to complete the query on your own.
select student_idstudent
,count(case when status like 'Absent' then 1 end) as absent_count
,count(case when status like 'Present' then 1 end) as present_count
,count(*) as tot_count
from attendance
where student_subject_subjectid = 102
group
by student_idstudent;
Also, using LIKE without any wild card characters is equal to using =. For clarity, the conditions should really be written status = 'Absent' and status = 'Present'. This is also more clear.
The same goes for like <number>. Do you mean student_subject_subjectid = 102, or do you have something else in mind?
With #ronnis help.
I came up with this answer.
SELECT student_idstudent,
count(CASE WHEN status = 'Present' then 1 END)/count(*)*100 as percentage
FROM attendence
where student_subject_subjectid = 102
group by student_idstudent;
Consider the table below.
The rule is - an employee cannot take a break (needs to clock out) from job num 1 before clocking in to job num 2. In this case the employee "A" was supposed to clock OUT instead of BREAK on jobnum 1 because he later clocked in to JobNum#2
Is it possible to write a query to find this in plain SQL?
Idea is to check if next record is proper one. To find next record one has to find first punchtime after current for same employee. Once this information is retrieved one can isolate record itself and check fields of interest, specifically is jobnum the same and [optionally] is punch_type 'IN'. If it is not, not exists evaluates to true and record is output.
select *
from #punch p
-- Isolate breaks only
where p.punch_type = 'BREAK'
-- The ones having no proper entry
and not exists
(
select null
-- The same table
from #punch a
where a.emplid = p.emplid
and a.jobnum = p.jobnum
-- Next record has punchtime from subquery
and a.punchtime = (select min (n.punchtime)
from #punch n
where n.emplid = p.emplid
and n.punchtime > p.punchtime
)
-- Optionally you might force next record to be 'IN'
and a.punch_type = 'IN'
)
Replace #punch with your table name. -- is comment in Sql Server; if you are not using this database, remove this lines. It is a good idea to tag your database and version as there are probably faster/better ways to do this.
Here is the SQL
select * from employees e1 cross join employees e2 where e1.JOBNUM = (e2.JOBNUM + 1)
and e1.PUNCH_TYPE = 'BREAK' and e2.PUNCH_TYPE = 'IN'
and e1.PUNCHTIME < e2.PUNCHTIME
and e1.EMPLID = e2.EMPLID
Is there a function for MySQL that will count the number of times a string occurs in another string or column? Basically I want:
SELECT
SUB_COUNT('my word', `my_column`) AS `match_count`
FROM `table`
Thanks!
EDIT:
I need to know how many times the string appears in a column for each row in a SELECT.
An obvious but unscalable way is like this
(LENGTH(`my_column`) - LENGTH(REPLACE(`my_column`, 'my word', '')))/LENGTH('my word')
Have you investigated Full Text search in MySQL?
I just needed to do something similar, but took a different approach. I copied the relevant string into a temp table where I can add columns to track an index through each occurrence on each row.
In my example, I'm looking for substrings " - " (space-dash-space) in product descriptions, with the intent of eventually chopping those apart to show as bullet points, and I'm analyzing the data like this to see how many "bullets" products typically have.
I suspect this is more efficient than repeatedly re-writing string values, but I haven't actually benchmarked.
SELECT
ccp.ProductID, p.ProductDescription, descrlen=LEN(p.ProductDescription),
bulletcnt=0, indx=0, lastmatchat=0
INTO #DescrBullets
FROM Private.CompositeCatalogProduct AS ccp WITH(NOLOCK)
INNER JOIN Products.Product AS p WITH(NOLOCK) ON p.ProductId = ccp.ProductID
WHERE ccp.CompositeCatalogID=53
DECLARE #rows INT = 1
WHILE #rows>0
BEGIN
-- find the next occurrence on each row that's still in play
UPDATE #DescrBullets
SET lastmatchat = PATINDEX('% - %',RIGHT(ProductDescription,descrlen-indx))
WHERE indx<descrlen
-- anywhere that a match was found, increment my counter, and move my
-- index "cursor" past it
UPDATE #DescrBullets
SET bulletcnt = bulletcnt + 1,
indx = indx + lastmatchat + 2
WHERE lastmatchat>0
SET #rows = ##ROWCOUNT
-- for all the ones that didn't have a match, advance indx past the end
-- so we don't need to reprocess on next iterations
UPDATE #DescrBullets
SET indx=descrlen
WHERE lastmatchat=0
RAISERROR('processing, %d products still have bullets', 0, 1, #rows) WITH NOWAIT
END
SELECT db.bulletcnt, occurs=COUNT(*)
FROM #DescrBullets AS db
GROUP BY db.bulletcnt
ORDER BY 1
I think you may be able to use the following example. I was trying to count the number of times a particular carton type was used when shipping.
SELECT carton_type, COUNT(carton_type) AS match_count
FROM carton_hdr
WHERE whse ='wh1'
GROUP BY "carton_type"
Your scenario:
SELECT my_column COUNT(my_column)
FROM my_table
WHERE my_column = 'my_word'
GROUP BY my_column
If you take out the "where" function, it will count the number of times each distinct entry appears in "my_column".