CREATE TABLE sales ( "customer_id" VARCHAR(1) ,"order_date" DATE ,"product_id" INTEGER );
INSERT INTO sales ( customer_id ,order_date ,product_id ) VALUES ( 'A' ,'2021-01-01' ,1 );
( 'A' ,'2021-01-01' ,2 );
( 'A' ,'2021-01-07' ,2 );
( 'A' ,'2021-01-10' ,3 );
( 'A' ,'2021-01-11' ,3 );
( 'A' ,'2021-01-11' ,3 );
( 'B' ,'2021-01-01' ,2 );
( 'B' ,'2021-01-02' ,2 );
( 'B' ,'2021-01-04' ,1 );
( 'B' ,'2021-01-11' ,1 );
( 'B' ,'2021-01-16' ,3 );
( 'B' ,'2021-02-01' ,3 );
( 'C' ,'2021-01-01' ,3 );
( 'C' ,'2021-01-01' ,3 );
( 'C' ,'2021-01-07' ,3 );
Since
you are using double codes in the column name and Oracle expecting
case sensitive name
only the first statement conforms the INSERT statement syntax, while
the rest should be fixed
So, the correct statements for all of those current lines would like to be the following:
INSERT INTO Sales
("customer_id",
"order_date",
"product_id")
VALUES
('A',
date'2021-01-01', -- date literal is fixed
1);
Related
In the Oracle documentation we read about the formating parameter that:
0999 Returns leading zeros.
9990 Returns trailing zeros.
I understand leading zeros: Display 000123 instead of 123.
But trailing zeros?
How is 9990 different from 9999?
How is 99.90 different from 99.99?
You could use trailing zeros when you are dealing with monetary values
eg
Table and data
create table payments (
payment number
) ;
insert into payments( payment )
select 11 from dual union all
select 11.1 from dual union all
select 11.11 from dual ;
Query
select payment amount from payments
union
select sum( payment ) from payments ;
-- result
AMOUNT
_________
11
11.1
11.11
33.21
If you write a query or view that applies trailing zeros, you'll be able to get a result that is more "usable" eg
create or replace view payments_view ( position_, description, amount )
as
select
1
, 'item'
, to_char( payment, '999,999.00' )
from payments
union
select
2
, 'total'
, to_char( sum( payment ), '999,999.00' )
from payments
;
select description, amount
from payments_view
order by position_
;
-- output
DESCRIPTION AMOUNT
______________ ______________
item 11.00
item 11.10
item 11.11
total 33.21
DBfiddle here.
{1} How is 9990 different from 9999? {2} How is 99.90 different from
99.99?
In order to make this "visible", please have a look at the resultset of the following query, which shows various function calls, the DUMP() (returning a code for the datatype, the length of its input in bytes, and the "internal representation" - UTF8 code points in decimal in this case), and the actual output. The resultset also contains 3 rows with values padded via LPAD() and RPAD(), respectively, in order to make the positions of the digits easier to see.
select
'to_char( 1,''9990'' )' function_
, dump( to_char( 1,'9990' ) ) dump_
, to_char( 1, '9990' ) output_
from dual union all
select 'to_char( 1,''9999'' )', dump( to_char( 1, '9999' ) )
, to_char( 1, '9999' )
from dual union all
select 'to_char( 1 )', dump( to_char( 1 ) )
, to_char( 1 )
from dual union all
select 'to_char( 1,''fm9990'' )', dump( to_char( 1,'fm9990' ) )
, to_char( 1, '9999' )
from dual union all
select 'to_char( 1,''fm9999'' )', dump( to_char( 1,'fm9999' ) )
, to_char( 1, '9999' )
from dual union all
select 'to_char( 0,''99.90'' )', dump( to_char( 0,'99.90' ) )
, to_char( 0, '99.90' )
from dual union all
select 'to_char( 0,''99.99'' )', dump( to_char( 0,'99.99' ) )
, to_char( 0, '99.99' )
from dual union all
select 'to_char( 0,''90.99'' )', dump( to_char( 0,'90.99' ) )
, to_char( 0, '90.99' )
from dual union all
select 'to_char( 0,''fm99.90'' )', dump( to_char( 0,'fm99.90' ) )
, to_char( 0, 'fm99.90' )
from dual union all
select 'to_char( 0,''fm99.99'' )', dump( to_char( 0,'fm99.99' ) )
, to_char( 0, 'fm99.99' )
from dual union all
select 'lpad( ''1'', 5, '' '' )', null, lpad( '1', 5, ' ' ) from dual union all
select 'lpad( ''12345'', 6, ''_'' )', null, lpad( '12345', 6, '_' ) from dual union all
select 'rpad( ''12345'', 6, ''_'' )', null, rpad( '12345', 6, '_' ) from dual
;
Result
FUNCTION_ DUMP_ OUTPUT_
__________________________ _________________________________ __________
to_char( 1,'9990' ) Typ=1 Len=5: 32,32,32,32,49 1
to_char( 1,'9999' ) Typ=1 Len=5: 32,32,32,32,49 1
to_char( 1 ) Typ=1 Len=1: 49 1
to_char( 1,'fm9990' ) Typ=1 Len=1: 49 1
to_char( 1,'fm9999' ) Typ=1 Len=1: 49 1
to_char( 0,'99.90' ) Typ=1 Len=6: 32,32,32,46,48,48 .00
to_char( 0,'99.99' ) Typ=1 Len=6: 32,32,32,46,48,48 .00
to_char( 0,'90.99' ) Typ=1 Len=6: 32,32,48,46,48,48 0.00
to_char( 0,'fm99.90' ) Typ=1 Len=3: 46,48,48 .00
to_char( 0,'fm99.99' ) Typ=1 Len=2: 48,46 0.
lpad( '1', 5, ' ' ) 1
lpad( '12345', 6, '_' ) _12345
rpad( '12345', 6, '_' ) 12345_
Answers to your questions:
{1} No difference. In both cases, the results get padded with blanks (1 extra space for the "sign"). The effect of the formatting is comparable to the output of LPAD() (see third line from the bottom of the result set).
{2} No difference.
As #Ponder Stibbons has mentioned, there will be a difference when the number contains a decimal point and you use the 'fm' format model modifier, as this will remove extraneous characters from the output.
DBfiddle here.
what im trying to do is to find number of saving account at each branch, and display the number and branch address.
here is code :
create type address as object
(
street varchar2(20),
city varchar2(10),
p_code varchar2(8)
);
create type Branch as object
(
BId varchar2(3),--branch id
brAddress address,
bPhone int
);
create table tb_Branch of Branch
(
bid primary key
);
create type account as object
(
accNum varchar2(4), --pk
accType varchar2(8), -- check(current, saving)
balance number(8,2)
BId_ref ref BId
);
create tb_account of account
(
accNum primary key,
constraint accType_const check(accType IN ('current','savings'))
);`
Please help!
thanks!
Maybe the following example (Oracle 12c) will help you to find a solution ... (the TYPEs and TABLEs may need tweaking).
Types and tables
-- types
create type address_t as object (
street varchar2(20)
, city varchar2(10)
, postcode varchar2(8)
)
/
create type branch_t as object (
brid varchar2(64)
, braddress address_t
, brphone varchar2(24)
)
/
create type account_t as object (
accnum varchar2(4)
, acctype varchar2(8)
, balance number(12,2)
)
/
-- tables
create table branches (
branch branch_t
, constraint branch_pk primary key ( branch.brid )
);
create table accounts (
id number generated always as identity primary key
, account_details account_t
, constraint acc_type_check check(
account_details.acctype in ('current','savings')
)
, branchid references branches( branch.brid )
);
Some INSERTs (table BRANCHES)
insert into branches ( branch )
values (
branch_t( '66-20-67'
, address_t( '1 High St', 'Edinburgh', 'EH1 1AA' )
, '00441155700340' )
) ;
-- trying to insert this again
-- gives us
-- ORA-00001: unique constraint (...BRANCH_PK) violated -> PK constraint working
insert into branches ( branch )
values (
branch_t( '88-45-13'
, address_t( '2 Princes St', 'Edinburgh', 'EH2 2BB' )
, '00441156800900' )
) ;
-- The BRANCHES table contains:
SQL> select * from branches;
BRANCH(BRID, BRADDRESS(STREET, CITY, POSTCODE), BRPHONE)
---------------------------------------------------------------------------------------------------------------------------
BRANCH_T('66-20-67', ADDRESS_T('1 High St', 'Edinburgh', 'EH1 1AA'), '00441155700340')
BRANCH_T('88-45-13', ADDRESS_T('2 Princes St', 'Edinburgh', 'EH2 2BB'), '00441156800900')
Populate the ACCOUNTS table
begin
insert into accounts ( account_details, branchid )
values ( account_t ( '7890', 'savings', 123456.78 ), '66-20-67' ) ;
insert into accounts ( account_details, branchid )
values ( account_t ( '7891', 'savings', 222222.22 ), '66-20-67' ) ;
insert into accounts ( account_details, branchid )
values ( account_t ( '7892', 'savings', 333333.33 ), '88-45-13' ) ;
insert into accounts ( account_details, branchid )
values ( account_t ( '6789', 'current', 234567.89 ), '88-45-13' ) ;
end;
/
-- fails due to CHECK constraint
insert into accounts ( account_details, branchid )
values ( account_t ( '1234', 'standard', 4567.89 ), '66-20-67' ) ;
-- ORA-02290: check constraint (...ACC_TYPE_CHECK) violated
Query
/*
from your question:
" what im trying to do is
to find number of saving account at each branch,
and display the number and branch address "
*/
-- suggested query
select
A.account_details.acctype as acctype
, B.branch.brid as branchid
, B.branch.braddress.city as city
, count( * )
from branches B
join accounts A on B.branch.brid = A.branchid
where A.account_details.acctype = 'savings'
group by A.account_details.acctype
, B.branch.brid
, B.branch.braddress.city ;
ACCTYPE BRANCHID CITY COUNT(*)
-------- ---------- ---------- ----------
savings 88-45-13 Edinburgh 1
savings 66-20-67 Edinburgh 2
How to do
udfo in ( Case when fund is null then 'a','b','c' else 'd' end )
because you can only do :
udfo in ( Case when fund is null then 'a' else 'd' end )
?
Use OR and two mutually exclusive conditions:
SELECT *
FROM your_table
WHERE ( fund IS NULL AND udfo IN ( 'a', 'b', 'c' ) )
OR ( fund IS NOT NULL AND udfo IN ( 'd' ) )
You could even implement it using a CASE statement:
SELECT *
FROM your_table
WHERE CASE WHEN fund IS NULL AND udfo IN ( 'a', 'b', 'c' )
THEN 1
WHEN fund IS NOT NULL AND udfo IN ( 'd' )
THEN 1
ELSE 0
END = 1
But I find the former version easier to read.
I'm trying to delete rows in a table only when there is a corresponding entry with a negative amount. The tricky part is there could be more positive than negative or more negative than positive.
value1 amt
12345 50
12345 50
12345 -50
12345 -50
abcde 40
abcde 40
abcde -40
11111 30
11111 -30
11111 -30
The result should be:
abcde 40
11111 -30
I have to apologize. I realized the posters data set was too simple. Here is a revised answer that I believe works.
Basically, you need to partition into pairs and then delete the pairs having sum() = 0.
create table t ( id varchar2(20), val number );
delete from t;
INSERT INTO t ( id, val ) values ( '12345', 50);
INSERT INTO t ( id, val ) values ( '12345', 50);
INSERT INTO t ( id, val ) values ( '12345', -50);
INSERT INTO t ( id, val ) values ( '12345', -50);
INSERT INTO t ( id, val ) values ( 'abcde', 40);
INSERT INTO t ( id, val ) values ( 'abcde', 40);
INSERT INTO t ( id, val ) values ( 'abcde', 20);
INSERT INTO t ( id, val ) values ( 'abcde', 40);
INSERT INTO t ( id, val ) values ( 'abcde', -40);
INSERT INTO t ( id, val ) values ( '11111', 30);
INSERT INTO t ( id, val ) values ( '11111', -30);
INSERT INTO t ( id, val ) values ( '11111', -30);
INSERT INTO t ( id, val ) values ( 'aaaaa', 10);
INSERT INTO t ( id, val ) values ( 'aaaaa', -30);
COMMIT;
MERGE INTO t
USING (WITH value_partition AS
(SELECT t.*,
ROW_NUMBER () OVER (PARTITION BY t.id, t.val ORDER BY ROWID) rn_in_value
FROM t)
SELECT sp.ROWID row_id,
sp.*,
CASE WHEN SUM (sp.val) OVER (PARTITION BY sp.id, ABS (sp.val), rn_in_value) = 0 THEN 'N' ELSE 'Y' END
keep_row
FROM value_partition sp) u
ON (t.ROWID = u.row_id
AND u.keep_row = 'N')
WHEN MATCHED THEN
UPDATE SET t.val = u.val
DELETE
WHERE u.keep_row = 'N';
SELECT * FROM t;
Ok so here are my tables in the database:
CREATE DATABASE Temp
GO --------------------------
USE Temp
GO --------------------------
CREATE TABLE Table1
(
Table1Id INT IDENTITY(1, 1) ,
Name VARCHAR(20) ,
CONSTRAINT pk_Table1 PRIMARY KEY ( Table1Id )
)
GO --------------------------
CREATE TABLE Table2
(
Table2Id INT IDENTITY(1, 1) ,
Table1Id INT ,
NAME VARCHAR(20) ,
TheDate SMALLDATETIME ,
CONSTRAINT pk_Table2 PRIMARY KEY ( Table2Id ) ,
CONSTRAINT fk_Table2_Table1 FOREIGN KEY ( Table1Id ) REFERENCES Table1 ( Table1Id )
)
GO --------------------------
INSERT INTO Table1
( Name )
VALUES ( 'Stack Overflow' )
GO --------------------------
INSERT INTO Table1
( Name )
VALUES ( 'Expert Sex Change' )
GO --------------------------
INSERT INTO Table1
( Name )
VALUES ( 'Code Project' )
GO --------------------------
INSERT INTO dbo.Table2
( Table1Id ,
NAME ,
TheDate
)
VALUES ( 1 ,
'S1' ,
'11-01-2012'
)
GO --------------------------
INSERT INTO dbo.Table2
( Table1Id ,
NAME ,
TheDate
)
VALUES ( 1 ,
'S2' ,
'11-01-2013'
)
GO --------------------------
INSERT INTO dbo.Table2
( Table1Id ,
NAME ,
TheDate
)
VALUES ( 2 ,
'E1' ,
'10-01-2013'
)
And here's my LINQ:
from t1 in Table1s
join t2 in Table2s.OrderByDescending(x => x.TheDate)
on t1.Table1Id equals t2.Table1Id into tt
from t2 in tt.DefaultIfEmpty()
select new
{
t1.Table1Id,
t1.Name,
t2.NAME,
t2.TheDate
}
This one returns:
Table1Id - Name - NAME - TheDate
1 - Stack Overflow - S2 - 11/1/2013
2 - Expert Sex Change - E1 - 10/1/2013
1 - Stack Overflow - S1 - 11/1/2012
3 - Code Project - null - null
I want the LINQ query not to return the third line, as is from an older Date Value.
I think I got it, the answer is:
from t1 in Table1s
join t2 in Table2s
on t1.Table1Id equals t2.Table1Id
into tt
from x in tt.DefaultIfEmpty()
// where ... t1 && x ..
orderby t1.Table1Id
group x by new {t1.Table1Id,t1.Name} into g
select new {
Table1Id = g.Key.Table1Id,
Name = g.Key.Name,
TheDate = g.Max(c => c.TheDate)
}