I know i don't have to use SQL but i have other code between declare begin and end . I just extracted this part and everything works except this . I get the following error:
Error report:
ORA-06550: line 5, column 5:
PL/SQL: ORA-00933: SQL command not properly ended
ORA-06550: line 3, column 5:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
This is the code:
DECLARE
BEGIN
UPDATE octombrie
SET nr_imprumut = I.nr
from (select book_date bd,count(book_date) nr
from rental
where to_char(book_date,'mm') like '10'
group by book_date) I
where data = I.bd;
END;
/
I don't get it what did i do wrong ?
EDIT: book_date will give me a day from the month of october. In that day multiple books are rented, so i find out how many books i rented by counting the number of times the same date apears (the rented books are in the rental table). I then take this data and Update October table(i put the number of books aka 'nr' where the date in the october table matches the date in which the books where rented);
DECLARE
BEGIN
UPDATE octombrie o
SET o.nr_imprumut =
(select count(r.book_date)
from rental r
where to_char(r.book_date,'mm') like '10' and o.data = r.book_date)
WHERE exists (select 1 from rental r
where to_char(r.book_date,'mm') like '10' and o.data = r.book_date);
END;
Use
where exists (select 1 from rental r
where to_char(r.book_date,'mm') like '10' and o.data = r.book_date)
if you want to update only those rows for which you found something in rental (otherwise ALL rows will be updated in octombrie)
Another variant (updates all October 2014 data in octombrie; for each data calculates the number of rental ON this data)
UPDATE octombrie o
SET o.nr_imprumut =
(select count(r.book_date)
from rental r
where r.book_date between trunc(o.data) and trunc(o.data) + 1 - 1/24/60/60)
WHERE o.data between to_date('2014-10-01','yyyy-mm-dd') and to_date('2014-10-31 23:59:59','yyyy-mm-dd hh24:mi:ss');
I guess you really wanted to something like that:
DECLARE
BEGIN
UPDATE octombrie o
SET o.nr_imprumut =
(SELECT count(1)
FROM rental r
WHERE r.book_date between o.data and o.data+1-1/86400)
WHERE data between to_date('2014-10-01','yyyy-mm-dd') and to_date('2014-10-31','yyyy-mm-dd');
END;
Note that the WHERE-clause of the UPDATE-statement specifies a year, I don't think you want to updated your records for all days in any october. Limiting the date like that (with a BETWEEN operator, but without a TO_CHAR) makes it possible to use an index on octombrie.data, something I hope you have.
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 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.
I am trying to do a cohort analysis and compare average number of rentals based on the renter's first rental year(= the year where a renter rented first time). Basically, I am asking the question: are we retaining renters whose first year renting was 2013 than renters whose first year was 2015?
Here is my code:
SELECT renter_id,
Min(Date_part('year', created_at)) AS first_rental_year,
( Count(trip_finish) ) AS number_of_trips
FROM bookings
WHERE state IN ( 'approved', 'aboard', 'ashore', 'concluded', 'disputed' )
AND first_rental_year = 2013
GROUP BY 1
ORDER BY 1;
The error message I get is:
ERROR: column "first_rental_year" does not exist
LINE 6: ... 'aboard', 'ashore', 'concluded', 'disputed') AND first_rent...
^
********** Error **********
ERROR: column "first_rental_year" does not exist
SQL state: 42703
Character: 208
Any help is much appreciated.
SELECT renter_id,
Count(trip_finish) AS number_of_trips
FROM (
SELECT renter_id,
trip_finish,
Min(Date_part('year', created_at)) AS first_rental_year
FROM bookings
WHERE state IN ( 'approved', 'aboard', 'ashore', 'concluded', 'disputed' )
) T
WHERE first_rental_year = 2013
GROUP BY renter_id
ORDER BY renter_id ;
ERROR:
SQL Error [42703]: ERROR: column XYZ does not exist
Check you have double quotes around Column Fields:
BAD:
update public."AppTime" t Set "CustomTask"= 'XYZ' where t.SharedAppId = 12890;
GOOD:
With double quotes around "SharedAppId"
update public."AppTime" t Set "CustomTask"= 'XYZ' where t."SharedAppId" = 12890;
If you created the table without quotes, you should not use quotes when querying it, and vice versa. This is explained in the manual: "If you want to write portable applications you are advised to always quote a particular name or never quote it"
When I execute this query in SQL Server Management Studio, this error appears:
'Msg 207, Level 16, State 1, Line 1
Invalid column name 'ACCOUNT_NO'.'
This is the code for the query:
DECLARE #largeaccnumber INT = ACCOUNT_NO
DECLARE #smallaccnumber INT
SET #smallaccnumber = (SELECT LEFT(#largeaccnumber, 6))
SELECT DNADRX.CODE,
DNADDR.NAME,
DNADDR.TYPE,
DNADDR.MAIL_NAME,
ADDRESS_LINE1,
ADDRESS_LINE2,
ADDRESS_LINE3,
TOWN_CITY,
COUNTY_STATE,
COUNTY_STATE_CODE,
COUNTRY,
POST_ZIP,
LAST_STAT_DATE,
ACCOUNT_NO
FROM DNADRX,
DNADDR,
BACCNT
WHERE DNADDR.CODE = DNADRX.ADDRESS_CODE
AND DNADDR.CODE = #smallaccnumber
ORDER BY DNADRX.CODE
I want the query to display the data from the columns of the different tables (the columns are listed in the SELECT bit of the query) from 3 different tables (DNADRX, DNADDR, BACCNT), and the factor linking all 3 tables together is the 6 digit code (ACCOUNT_NO in the BACCNT table, ADDRESS_CODE in the DNADRX table and CODE in the DNADDR table). Originally, ACCOUNT_NO from table BACCNT was 8 digits long, but I reduced it to the first 6 digits using SELECT LEFT and assigned this 6 digit value to the variable #smallaccnumber.
Whenever I try to execute the query, it keeps telling me that 'ACCOUNT_NO' is an invalid code name. I have checked the spelling, refreshed using IntelliSense and tried 'BACCNT.ACCOUNT_NO' instead of just 'ACCOUNT_NO' on the first line of the query but it still won't work (instead it says that the multi-part identifier could not be bound when I try 'BACCNT.ACCOUNT_NO').
I am really new to SQL coding so sorry if the answer to my problem is really simple.
Thank you for your assistance :)
You can try something like this.
This assumes you know the 6 character code. This query will only find results IF there is a record matching in EVERY table. If one table doesn't find a matching record this query will return NOTHING. If you want to find a row even if a recrod is missing from a table, replace the "INNER JOIN" with "LEFT OUTER JOIN"
SELECT Dnadrx.Code,
Dnaddr.Name,
Dnaddr.Type,
Dnaddr.Mail_Name,
Address_Line1,
Address_Line2,
Address_Line3,
Town_City,
County_State,
County_State_Code,
Country,
Post_Zip,
Last_Stat_Date,
Account_No
FROM Dnaddr
INNER JOIN BACCNT ON DNAADDR.CODE = BACCNT.ACCOUNT_NO
INNER JOIN Dnadrx ON Dnaaddr.Code=Dnaadrx.Address_Code
WHERE Dnaddr.Code='YOUR 6 CHARACTER CODE GOES HERE'
ORDER BY Dnadrx.Code;
I'm trying to write Firebird stored procedure, which returns me cumulative sums for twelve months grouped by another two fields.
For now I created something like this:
SET TERM ^ ;
CREATE PROCEDURE A_OBRATZISKKUM(
START_YEAR INTEGER,
END_YEAR INTEGER)
RETURNS(
OBRAT DOUBLE PRECISION,
MESIC INTEGER,
ROK INTEGER,
SECURITYUSER_ID TYPE OF ID COLLATE WIN1250,
FIRM_ID TYPE OF ID COLLATE WIN1250)
AS
DECLARE VARIABLE act_month INTEGER = 1;
begin
for select
sum(AO.Obrat), :act_MONTH, :start_YEAR, AO.SecurityUser_ID,
AO.Firm_ID
from A_OBRATYKUMHIST_TEMP AO
where
AO.Rok = :start_year
and AO.Mesic <= :act_month
group by
AO.SecurityUser_ID, AO.Firm_ID
into :obrat, :mesic, :rok, :securityuser_id, :firm_id
do
act_month = :act_MONTH + 1;
suspend;
end^
SET TERM ; ^
But when I run it I get only one row with weird sum. What's wrong on my code?
EDIT1.
I come out from this sql query:
select
sum(AO.Obrat), *1*, 2012, AO.SecurityUser_ID,
AO.Firm_ID
from A_OBRATYKUMHIST_TEMP AO
where
AO.Rok = 2012
and AO.Mesic <= *1*
group by
AO.SecurityUser_ID, AO.Firm_ID
When I take for example month number 3, I get sum of all previous months grouped by securityuser_id and firm_id.
But if I want to get sums for all months, then I have to run this twelve times with replacing 1 for 2, then for 3, then ........
At the end I get cumulative sums splits up to months, years, users and firms.
A DO is followed by either a single statement, or by a block. You are currently doing a single SUSPEND instead of multiple suspends as your intention is. Instead of
FOR SELECT ...
DO
statement;
SUSPEND;
You need to do
FOR SELECT ...
DO
BEGIN
statement;
SUSPEND;
END
Also the statement act_month = :act_MONTH + 1; should be act_month = act_MONTH + 1; (no colon :)
The running sum
The running sum can be achieved by self-joining for all months <= the current month and summing over that:
SELECT SUM(AO2.Obrat), AO.Mesic, AO.Rok, AO.SecurityUser_ID, AO.Firm_ID
FROM A_OBRATYKUMHIST_TEMP AO
INNER JOIN A_OBRATYKUMHIST_TEMP AO2
ON AO2.Rok = AO.Rok AND AO2.Mesic <= AO.Mesic
WHERE AO.Rok = 2012
GROUP BY AO.Mesic, AO.Rok, AO.SecurityUser_ID, AO.Firm_ID
Note this only works within the same year, you'd need to modify the join condition if you need to sum over multiple years.