I have a test which uses H2 as an in memory database. The following table, data and query produces a single row in MySQL with the expected values, but not in H2:
CREATE TABLE redirects (
site_id INTEGER NOT NULL,
company_id INTEGER NOT NULL,
type CHAR(1) NOT NULL,
capture TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO redirects (site_id, company_id, type, capture) VALUES (1, 1, 'm', CURRENT_TIMESTAMP);
INSERT INTO redirects (site_id, company_id, type, capture) VALUES (1, 2, 'm', CURRENT_TIMESTAMP);
INSERT INTO redirects (site_id, company_id, type, capture) VALUES (1, 1, 'h', CURRENT_TIMESTAMP);
INSERT INTO redirects (site_id, company_id, type, capture) VALUES (1, 1, 'h', CURRENT_TIMESTAMP);
INSERT INTO redirects (site_id, company_id, type, capture) VALUES (1, 2, 'h', CURRENT_TIMESTAMP);
INSERT INTO redirects (site_id, company_id, type, capture) VALUES (1, 1, 'a', CURRENT_TIMESTAMP);
INSERT INTO redirects (site_id, company_id, type, capture) VALUES (1, 1, 'a', CURRENT_TIMESTAMP);
INSERT INTO redirects (site_id, company_id, type, capture) VALUES (1, 1, 'a', CURRENT_TIMESTAMP);
INSERT INTO redirects (site_id, company_id, type, capture) VALUES (1, 2, 'a', CURRENT_TIMESTAMP);
SELECT
COALESCE(site_id, 1) site_id,
COALESCE(company_id, -1) company_id,
COUNT(CASE WHEN type = 'm' THEN 1 END) views,
COUNT(CASE WHEN type IN ('h', 'a') THEN 1 END) clicks
FROM
redirects
WHERE
(site_id = 1 AND company_id = 3 AND capture > TIMESTAMP '2017-04-24 00:00:00.0');
The result in MySQL is the following:
+---------+------------+-------+--------+
| site_id | company_id | views | clicks |
+---------+------------+-------+--------+
| 1 | -1 | 0 | 0 |
+---------+------------+-------+--------+
However, in H2 (version 1.4.194) the result is:
SITE_ID COMPANY_ID VIEWS CLICKS
1 2 0 0
Related
I am having TEST schema and it has many tables.
I want to find table details like
Table name, column name, column datatype, column length, column default value, column allow null, column comment
I am using Oracle database, please guide me how to do this.
In SQL developer I am able to find these details for individual table but I want to get this for tables where table name starts with A,B or C (this can be any alphabet character)
If you are logged in as a DBA user, you can use:
SELECT *
FROM dba_tab_columns
WHERE OWNER = 'TEST'
AND SUBSTR(TABLE_NAME, 1, 1) IN ('A', 'B', 'C', 'a', 'b', 'c');
Or you can query the all_tab_columns data dictionary view or, if you are logged in as the TEST user:
SELECT *
FROM user_tab_columns
WHERE SUBSTR(TABLE_NAME, 1, 1) IN ('A', 'B', 'C', 'a', 'b', 'c');
select * from ALL_TAB_COLUMNS
where
OWNER = 'TEST'
and SUBSTR(TABLE_NAME, 1, 1) IN ('A', 'B', 'C', 'a', 'b', 'c');
this will give you column names and info of all tables accessible to the current user
https://docs.oracle.com/cd/B19306_01/server.102/b14237/statviews_2094.htm
Hi devs I'm developing a small pro bono project that's use oracle sql but I'm not able to hide the null results.
Table Structure:
CREATE TABLE "church-members" (
ID NUMBER(10),
NAME varchar(30) NOT NULL,
LOGIN varchar(20) NOT NULL,
PASS varchar(12) NOT NULL,
REGISTER_YEAR_MONTH varchar(15) NOT NULL,
USER_SCORE NUMBER(10),
PRIMARY KEY (ID));
The queries:
INSERT INTO "church-members" VALUES
('1', 'John Doe', 'John', 'Xo8*d_d%f58*', '202204','1');
INSERT INTO "church-members" VALUES
('2', 'Mary Doe', 'Mary', 'dLoc&257dsew', '202203','2');
INSERT INTO "church-members" VALUES
('3', 'Robertson III', 'Robertson', 'koIIf59*Liu*', '202203','7');
INSERT INTO "church-members" VALUES
('4', 'Sonia MacDonald', 'Sonia', 'fYhfgtdjfi%', '202204','4');
INSERT INTO "church-members" VALUES
('5', 'Boris Johnston', 'Boris', 'do*&flddkIK%', '202201','2');
INSERT INTO "church-members" VALUES
('6', 'Ruth Henderson', 'Ruth', 'dF6%*&', '202202','2');
The Select:
SELECT
ID,
NAME,
LOGIN,
MAX(CASE WHEN REGISTER_YEAR_MONTH = '202203' THEN TO_CHAR(USER_SCORE) ELSE '' END) AS "MARCH SCORE",
MAX(CASE WHEN REGISTER_YEAR_MONTH = '202204' THEN TO_CHAR(USER_SCORE) ELSE '' END) AS "APRIL SCORE "
FROM
"church-members"
GROUP BY
ID,
NAME,
LOGIN
And the result fiddle:
https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=a4deac5e3eefb17dca97661552458a61
I got to this point using the information obtained in the answer from this link:
Select more than one column and remove NULL values from result
Looking at the fiddle example, the results with IDs 5 and 6 should not be showing because both are nulls.
But still null results are being shown...
Can anyone help me to solve it?
Add a HAVING clause requiring that each matching ID have at least data for at least one of the two months:
SELECT ID, NAME, LOGIN,
MAX(CASE WHEN REGISTER_YEAR_MONTH = '202203' THEN TO_CHAR(USER_SCORE) END) AS "MARCH SCORE",
MAX(CASE WHEN REGISTER_YEAR_MONTH = '202204' THEN TO_CHAR(USER_SCORE) END) AS "APRIL SCORE"
FROM "church-members"
GROUP BY ID, NAME, LOGIN
HAVING COUNT(CASE WHEN REGISTER_YEAR_MONTH IN ('202203', '202204') THEN 1 END) > 0;
What would be the most performant oracle query (not a procedure) for searching the jobs which have only inactive employees for the below tables. *I cannot change DB structure.
Job table
id
name
0
j0
1
j1
2
j2
3
j3
4
j4
...
JoinTable table
id
job_id
employee_id
0
0
0
1
0
1
2
1
0
3
1
2
4
2
2
5
2
3
6
3
2
7
3
4
8
4
3
...
Employee table
id
status
0
active
1
active
2
inactive
3
inactive
4
null
...
Result should be like:
name
j2
j4
Create and inserts:
CREATE TABLE job(
id int,
name char(50)
);
CREATE TABLE jointable(
id int,
job_id int,
employee_id int
);
CREATE TABLE employee(
id int,
status char(50)
);
INSERT INTO job (id, name) VALUES (0, 'j0');
INSERT INTO job (id, name) VALUES (1, 'j1');
INSERT INTO job (id, name) VALUES (2, 'j2');
INSERT INTO job (id, name) VALUES (3, 'j3');
INSERT INTO job (id, name) VALUES (4, 'j4');
INSERT INTO employee (id, status) VALUES (0, 'active');
INSERT INTO employee (id, status) VALUES (1, 'active');
INSERT INTO employee (id, status) VALUES (2, 'inactive');
INSERT INTO employee (id, status) VALUES (3, 'inactive');
INSERT INTO employee (id, status) VALUES (4, null);
INSERT INTO jointable (id, job_id, employee_id) VALUES (0, 0, 0);
INSERT INTO jointable (id, job_id, employee_id) VALUES (1, 0, 1);
INSERT INTO jointable (id, job_id, employee_id) VALUES (2, 1, 0);
INSERT INTO jointable (id, job_id, employee_id) VALUES (3, 1, 2);
INSERT INTO jointable (id, job_id, employee_id) VALUES (4, 2, 2);
INSERT INTO jointable (id, job_id, employee_id) VALUES (5, 2, 3);
INSERT INTO jointable (id, job_id, employee_id) VALUES (6, 3, 2);
INSERT INTO jointable (id, job_id, employee_id) VALUES (7, 3, 4);
INSERT INTO jointable (id, job_id, employee_id) VALUES (8, 4, 3);
I've tried something like:
select j.name from job j
left join jointable jt on j.id = jt.job_id
left join employee e on jt.employee_id = e.id
where e.status = 'inactive'
-- where not exists(select status from employee where status <> active and status <> null)
-- where exists(select status from employee where status = 'inactive')
order by j.id desc;
I'm not sure how to incroporate in, having, count or proper where clauses to achive the reqirement.. or maybe i should use something else. Thanks in advance.
Maybe a little more performant than Ankit's query as this one fetches data from each of your tables only once.
SQL> with temp as
2 (select j.name,
3 min(nvl(e.status, '-')) min_status,
4 max(nvl(e.status, '-')) max_status
5 from job j join jointable t on t.job_id = j.id
6 join employee e on e.id = t.employee_id
7 group by j.name
8 )
9 select x.name
10 from temp x
11 where x.min_status = x.max_status
12 and x.min_status = 'inactive';
NAME
----
j2
j4
SQL>
I think you may try below query -
SELECT DISTINCT J.name
FROM Job J
JOIN JoinTable JT ON J.id = JT.job_id
JOIN Employee E ON JT.employee_id = E.id
WHERE E.status = 'inactive'
AND NOT EXISTS (SELECT NULL
FROM Employee E2
JOIN JoinTable JT2 ON JT2.employee_id = E2.id
WHERE COALESCE(E2.status, 'I') <> 'inactive'
AND J.id = JT2.job_id);
Fiddle Demo.
I have a table where values in certain columns can change. My requirement is to identify the items(id) where the value has changed. E.g.
Input:
ID VALUE1 VALUE2 VALUE3
1 A B C
1 X B C
2 D E F
2 D E F
3 G H I
3 S H T
Output Needed:
ID VALUE1 VALUE2 VALUE3
1 X
3 S T
I am using Oracle SQL. ANy help will be appreciated
This could be a way, assuming that you need to order your records by some column (I added a row_num column just to explain):
select *
from (
select ID,
case when lag(value1) over (partition by ID order by row_num) != value1 then value1 end as value1,
case when lag(value2) over (partition by ID order by row_num) != value2 then value2 end as value2,
case when lag(value3) over (partition by ID order by row_num) != value3 then value3 end as value3
from yourTable
)
where value1 is not null
or value2 is not null
or value3 is not null
This uses lag to get the value in the preceding row (ordered by row_num) for the same ID and then simply checks if there's at least one difference.
With your sample data, this
with yourTable(row_num, ID, VALUE1, VALUE2, VALUE3) as (
select 1, 1, 'A', 'B', 'C' from dual union all
select 2, 1, 'X', 'B', 'C' from dual union all
select 3, 2, 'D', 'E', 'F' from dual union all
select 4, 2, 'D', 'E', 'F' from dual union all
select 5, 3, 'G', 'H', 'I' from dual union all
select 6, 3, 'S', 'H', 'T' from dual
)
select *
from (
select ID,
case when lag(value1) over (partition by ID order by row_num) != value1 then value1 end as value1,
case when lag(value2) over (partition by ID order by row_num) != value2 then value2 end as value2,
case when lag(value3) over (partition by ID order by row_num) != value3 then value3 end as value3
from yourTable
)
where value1 is not null
or value2 is not null
or value3 is not null
gives
ID VALUE1 VALUE2 VALUE3
---------- ------ ------ ------
1 X
3 S T
2 rows selected.
Your solution needs three parts.
You need to define an order for the changes. In your example it is "from top down to bottom". In your table, you'll have likely a date column or numerical id.
As #Aleksej suggests, you can then access the previous value with LAG(value) OVER (... ORDER BY ...)
You need a comparision function, which handles NULL values correctly. This is a bit painful, and there are more solutions to it, none of which is nice. I'd recommend DECODE(old_value, new_value, 0, 1)=1, see here for other examples.
I've added some extra rows to your table to test the changes involving NULL values:
CREATE TABLE mytable (id NUMBER, value1 VARCHAR2(1), value2 VARCHAR2(1), value3 VARCHAR2(1), t TIMESTAMP DEFAULT SYSTIMESTAMP);
INSERT INTO mytable (id,value1,value2,value3) VALUES (1, 'A','B','C');
INSERT INTO mytable (id,value1,value2,value3) VALUES (1, 'X','B','C');
INSERT INTO mytable (id,value1,value2,value3) VALUES (2, 'D','E','F');
INSERT INTO mytable (id,value1,value2,value3) VALUES (2, 'D','E','F');
INSERT INTO mytable (id,value1,value2,value3) VALUES (3, 'G','H','I');
INSERT INTO mytable (id,value1,value2,value3) VALUES (3, 'S','H','T');
INSERT INTO mytable (id,value1,value2,value3) VALUES (3, 'S','H',NULL);
INSERT INTO mytable (id,value1,value2,value3) VALUES (3, 'S','H',NULL);
INSERT INTO mytable (id,value1,value2,value3) VALUES (3, 'S','U','T');
SELECT ID,
CASE WHEN value1_changed=1 THEN value1 END AS value1,
CASE WHEN value2_changed=1 THEN value2 END AS value2,
CASE WHEN value3_changed=1 THEN value3 END AS value3,
value1_changed,
value2_changed,
value3_changed
FROM (
SELECT id, value1, value2, value3,
DECODE(value1, LAG(value1) OVER (PARTITION BY ID ORDER BY t), 0, 1) value1_changed,
DECODE(value2, LAG(value2) OVER (PARTITION BY ID ORDER BY t), 0, 1) value2_changed,
DECODE(value3, LAG(value3) OVER (PARTITION BY ID ORDER BY t), 0, 1) value3_changed,
row_number() OVER (PARTITION BY ID ORDER BY t) AS r, t
FROM mytable
)
WHERE r > 1
AND value1_changed + value2_changed + value3_changed >= 0;
ID value1 value2 value3 changed1 changed2 changed3
1 X 1 0 0
3 S T 1 0 1
3 0 0 1
3 U 0 0 1
Please not the 3rd line, when value3 changed from 'T' to NULL. It gets correctly reported, but only with it's new value NULL.
I have a simple hierarchy structure in a table (Using Oracle Database 11g)
A
|-B
|-B1
|-C
|-D
Each node has a property associated with it (Y or N).
Traversing from the root node (parent), I want to get the first node in each branch that has the property Y.
For example:
A
|-B (N)
|-B1 (Y)
|--B2 (N)
|-C (Y)
|-C1 (Y)
|--C2 (N)
|-D (Y)
This should return B1, C and D.
Please give some ideas on how this can be done (code needs to be optimized for time).
There's probably a fancier way than using sys_connect_by_path, but I find it very easy to understand.
create table hier_test (id varchar2(2), parent_id varchar2(2), prop varchar2(1));
insert into hier_test values ('A', null, 'N');
insert into hier_test values ('B', 'A', 'N');
insert into hier_test values ('C', 'A', 'Y');
insert into hier_test values ('D', 'A', 'Y');
insert into hier_test values ('B1', 'B', 'Y');
insert into hier_test values ('B2', 'B1', 'N');
insert into hier_test values ('C1', 'C', 'Y');
insert into hier_test values ('C2', 'C1', 'N');
select id from (
select id, prop, sys_connect_by_path(prop, '>') as priors
from hier_test
connect by parent_id = prior id
start with id = 'A'
)
where prop = 'Y' and priors not like '%Y>%';
Edit: sqlfiddle