Oracle SQL Query to get missing date from two joined tables - oracle

I'm trying to write a Oracle SQL query and I'm unable to get the right result.
For the tables below, I would like to first get all records from DEVICE where DEVICE.MODEL='UNITA' and for those results, give me the DEVICE.CUSTOMER_ID's who don't have a record where PROFILE.TYPE='TEST' joining both tables on CUSTOMER_ID. Any ideas on how to formulate this query?
TABLE DEVICE:
ID - sequence generated primary key (NUMBER (10))
DEVICE_NUMBER - unique (varchar)
CUSTOMER_ID (varchar)
MODEL (varchar)
TABLE PROFILE:
ID - sequence generated primary key (NUMBER (10))
CUSTOMER_ID (varchar)
TYPE (varchar)

If I understand the requirement, this should do the trick:
SELECT d.ID, d.Device_Number, d.Customer_ID, d.Model
FROM Device d
LEFT JOIN Profile p ON d.Customer_ID = p.Customer_ID
WHERE d.Model = 'UNITA'
AND (p.ID IS NULL OR p.Type = 'TEST')
It works because of the LEFT JOIN, which will make Profile.ID NULL if there's not a matching Profile row for the Customer_ID. If there is a matching row, the test for Profile.Type = 'TEST' will determine what's included.
There's a SQL Fiddle here. The Fiddle includes the Profile.ID and Profile.Type values in the results because I think they help explain things more clearly.
Addendum: Some confusion on my part over the requirements; this query may be closer to what's needed:
SELECT d.ID, d.Device_Number, d.Customer_ID, d.Model, p.id AS pid, p.type
FROM Device d
LEFT JOIN Profile p ON d.Customer_ID = p.Customer_ID AND p.Type = 'TEST'
WHERE d.Model = 'UNITA'
AND p.ID IS NULL

Related

Using query hints to use a index in an inner table

I have a query which uses the view a as follows and the query is extremely slow.
select *
from a
where a.id = 1 and a.name = 'Ann';
The view a is made up another four views b,c,d,e.
select b.id, c.name, c.age, e.town
from b,c,d,e
where c.name = b.name AND c.id = d.id AND d.name = e.name;
I have created an index on the table of c named c_test and I need to use it when executing the first query.
Is this possible?
Are you really using this deprecated 1980s join syntax? You shouldn't. Use proper explicit joins (INNER JOIN in your case).
You are joining the two tables C and D on their IDs. That should mean they are 1:1 related. If not, "ID" is a misnomer, because an ID is supposed to identify a row.
Now let's look at the access route: You have the ID from table B and the name from tables B and C. We can tell from the column name that b.id is unique and Oracle guarantees this with a unique index, if the database is set up properly.
This means the DBMS will look for the B row with ID 1, find it instantly in the index, find the row instantly in the table, see the name and see whether it matches 'Ann'.
The only thing that can be slow hence is joining C, D, and E. Joining on unique IDs is extremely fast. Joining on (non-unigue?) names is only fast, if you provide indexes on the names. I'd recommend the following indexes accordingly:
create index idx_c on c (name);
create index idx_e on e (name);
To get this faster still, use covering indexes instead:
create index idx_b on b (id, name);
create index idx_c on c (name, id, age);
create index idx_d on d (id, name);
create index idx_e on e (name, town);

Join to another table when the join column is null

I have a sql that is selecting many things from the database however I would like that data to only comeback which is matched to a personal table I have.
I would like to join a column [vin_code] from my table [population] however there are nulls in here and were there are nulls I would like to join another column from my table to another table in the database.
I will give an example sql below:
Select distinct v.kegal_rntity_id
From vin v
Inner join ops$dami.population pop
On v.vin_code = pop.vin_code
Then were pop.vin_code is null I would like to join pop.vis_code on a table in the database called zegal_rentity z column z.vis_code
So something like
join zegal_rentity z
On pop.vis_code = z.vis_code
But I only want to do this were pop.vin_code is null
As sample data is not available, I am unable to test the solution but try the following query with condition based outer join.
Select distinct v.kegal_rntity_id
From ops$dami.population pop
Left join vin v
On v.vin_code = pop.vin_code
Left join zegal_rentity z
On (case when pop.vin_code is null and
pop.vis_code = z.vis_code then 1 end = 1);
Cheers!!

oracle select query based on other table row level condition

I want to find the orders number from table#orders where DelivaryDateRevision less than max revisions from each country(table#maxrevisions). Countrycode is not the foreign key to the other table.
Can I fetch the orders table records if the country code is missing in the maxrevisions table.
Table: orders
OrderNumber | CountryCode | DelivaryDateRevision
123--------------- IN-------------------9
234--------------- US-------------------3
238-------------- IN------------------ 3
table: maxrevisions
CountryCode| MaxRevision
IN ---------------6
US--------------- 4
My query:
SELECT distinct o.ordernumber,o.countrycode
FROM orders o
left outer join maxrevisions m
on o.CountryCode=m.CountryCode
and
o.DelivaryDateRevision<rs.MaxRevision;
but I am getting the wrong result. Can I get any help here?
Your major omission seems to be a WHERE clause which compares the two revisions:
SELECT
o.ordernumber,
o.countrycode
FROM orders o
LEFT JOIN maxrevisions m
ON o.CountryCode = m.CountryCode
WHERE
o.DelivaryDateRevision < m.MaxRevision OR m.MaxRevision IS NULL;
Demo
Select
ordernumber,
countrycode,
deliverydateversion
from orders o
where deliverydateversion >
(
select max(revision)
from maxrevisiontab
where countrycode= o.countrycode
)
Please change the table names and column names as per your structure.

Why is "group by" giving only one column as output?

I have a table something like this:
ID|Value
01|1
02|4
03|12
01|5
02|14
03|22
01|9
02|32
02|62
01|13
03|92
I want to know how much progress have each id made (from initial or minimal value)
so in sybase I can type:
select ID, (value-min(value)) from table group by id;
ID|Value
01|0
01|4
01|8
01|12
02|0
02|10
02|28
02|58
03|0
03|10
03|80
But monetdb does not support this (I am not sure may be cz it uses SQL'99).
Group by only gives one column or may be average of other values but not the desired result.
Are there any alternative to group by in monetdb?
You can achieve this with a self join. The idea is that you build a subselect that gives you the minimum value for each id, and then join that to the original table by id.
SELECT a.id, a.value-b.min_value
FROM "table" a INNER JOIN
(SELECT id, MIN(value) AS min_value FROM "table" GROUP BY id) AS b
ON a.id = b.id;

How do I write a LINQ query to combine multiple rows into one row?

I have one table, 'a', with id and timestamp. Another table, 'b', has N multiple rows referring to id, and each row has 'type', and "some other data".
I want a LINQ query to produce a single row with id, timestamp, and "some other data" x N. Like this:
1 | 4671 | 46.5 | 56.5
where 46.5 is from one row of 'b', and 56.5 is from another row; both with the same id.
I have a working query in SQLite, but I am new to LINQ. I dont know where to start - I don't think this is a JOIN at all.
SELECT
a.id as id,
a.seconds,
COALESCE(
(SELECT b.some_data FROM
b WHERE
b.id=a.id AND b.type=1), '') AS 'data_one',
COALESCE(
(SELECT b.some_data FROM
b WHERE
b.id=a.id AND b.type=2), '') AS 'data_two'
FROM a first
WHERE first.id=1
GROUP BY first.ID
you didn't mention if you are using Linq to sql or linq to entities. However following query should get u there
(from x in a
join y in b on x.id equals y.id
select new{x.id, x.seconds, y.some_data, y.type}).GroupBy(x=>new{x.id,x.seconds}).
Select(x=>new{
id = x.key.id,
seconds = x.Key.seconds,
data_one = x.Where(z=>z.type == 1).Select(g=>g.some_data).FirstOrDefault(),
data_two = x.Where(z=>z.type == 2).Select(g=>g.some_data).FirstOrDefault()
});
Obviously, you have to prefix your table names with datacontext or Objectcontext depending upon the underlying provider.
What you want to do is similar to pivoting, see Is it possible to Pivot data using LINQ?. The difference here is that you don't really need to aggregate (like a standard pivot), so you'll need to use Max or some similar method that can simulate selecting a single varchar field.

Resources