Laravel JOIN query with 2 conditions out of which one is NULL - laravel

I need a query where I want to join tables, on 2 conditions in OR. Out of these 2 condition is to check whether the column IS NULL.
$query->select('users.*', 'o.name', 'r.name')
->join('owners as o', 'users.owner_id', '=', 'o.id')
->join('residents as r', 'users.resident_id', '=', 'r.id');
In the above query I also want to check if the users.resident_id IS NULL i.e., users.resident_id = r.id OR users.resident_id IS NULL.
Thanks for your time and help in advance.

i haven't try this..
how about use "right join" sql..
from w3school..
SQL RIGHT JOIN Keyword. The RIGHT JOIN keyword returns all records from the right table (table2), and the matched records from the left table (table1). The result is NULL from the left side, when there is no match.
if this not working then use "whereIn"..
select all id with null data first, then select all id from join.. then you can use whereIn to select all data with id from data1 and data2..

Related

Trying to update a field in Oracle based on a select statement - getting subquery returns more than one row error

I am trying to update a field on a table the query needs to get the value from a 2nd table and use that to get the data from a 3rd table. I keep getting the "ORA-01427: single-row subquery returns more than one row" Any help is appreciated.
update ord_detail set cuser1 = (select c.email from contact c,ord_detail m join orders o on o.ID = m.orders_ID where c.email is not null)
where EXISTS (select email from contact,orders where orders.contact_id2 = contact.id)
Since you did not provide further information like the results of your sub selects, it's not 100% clear what exactly is your problem. You should check those results and if this does not answer your question, please provide the details.
My guess is that this sub query will give multiple rows because you are missing a join from the table "contact" to one of the other tables:
select c.email from contact c,ord_detail m
join orders o on o.ID = m.orders_ID where c.email is not null
Therefore, this sub query will always lead to many rows as result unless the table "contact" contains one row only whose column email is not null.

Getting ORA-01427 trying to select all from view I've created

I created a view from tables using these queries
CREATE VIEW AVAIL_TOOLS AS
SELECT T.TOOL_NAME AS "Name", R.RETAILER_NAME AS "Retailer", T.RETAILER_NUM AS "Number", I.TI_STATUS AS "Status",
(SELECT
CASE
WHEN DETAIL_RETURNDATE IS NULL THEN TO_CHAR(DETAIL_DUEDATE,'Day, Month, DD, YYYY')
ELSE 'Now' END FROM DETAILRENTAL) AS "Expected Avaliablity"
FROM TOOL T
INNER JOIN RETAILER R
ON T.RETAILER_NUM = R.RETAILER_NUM
INNER JOIN TOOLINSTANCE I
ON T.TOOL_NUM = I.TOOL_NUM
WHERE (I.TI_STATUS = 'Rented') OR (I.TI_STATUS = 'Available')
ORDER BY T.TOOL_NAME;
now when I try to run SELECT * FROM AVAIL_TOOLS
I receive the error ORA-01427: single-row subquery returns more than one row.
The case I am running in the query obviously seems to be the problem. Now is there anyway I could change the queries around. I am trying to create a view where if the return date is null it will be available when it is returned other wise it should be now.
I'm at a loss on how I should change about to get the resulted needed.
Query below should do what you want when you fill proper join condition.
CREATE VIEW AVAIL_TOOLS AS
SELECT T.TOOL_NAME AS "Name", R.RETAILER_NAME AS "Retailer", T.RETAILER_NUM AS "Number", I.TI_STATUS AS "Status",
CASE
WHEN DETAIL_RETURNDATE IS NULL THEN TO_CHAR(DETAIL_DUEDATE,'Day, Month, DD, YYYY')
ELSE 'Now' END "Expected Avaliablity"
FROM TOOL T
INNER JOIN RETAILER R
ON T.RETAILER_NUM = R.RETAILER_NUM
INNER JOIN TOOLINSTANCE I
ON T.TOOL_NUM = I.TOOL_NUM
LEFT OUTER JOIN DETAILRENTAL DR
ON (I.ID? = DR.TOOL_INSTANCE_ID?) --HERE fill join
WHERE (I.TI_STATUS = 'Rented') OR (I.TI_STATUS = 'Available')
ORDER BY T.TOOL_NAME;
Second option is adding to subquery with case where clause based on the same condition as join:
where I.INSTANCE_ID = DETAILRENTAL.INSTANCE_ID
You are combining the result of that CASE expression for ALL rows in DETAILRENTAL with ALL the rows from the three-table join. Instead, you probably only want the "expected availability" for the specific tool in the main SELECT. You could fix it by making the subquery into a correlated subquery; but it makes more sense to just have the CASE expression as a column in the outer SELECT, not wrapped within a subquery, and to add a join to DETAILRENTAL on whatever you need to join on (probably TOOL_NUM?)

HIve join without common filed

I have the following tables:
Table1:
user_name Url
Rahul www.cric.info.com
ranbir www.rogby.com
sahil www.google.com
banit www.yahoo.com
Table2:
Keyword category
cric sports
footbal sports
google search
I want to search Table1 by matching the keyword in Table2. I can perform the same using case statement and the query works but it is not the right approach because each time I have to add the case statement when I will add new search keyword.
select user_name from table1
case when url like '%cric%' then sports
else 'undefined'
end as category
from table1;
Thanks find the soluntions for this approach. FIrst we need to do the Join and after that we need to filter the record.
select user_name,url,Keyword,catagory from(select table1.user_name,table1.url ,table2.keyword,table2.catagory from table1 left outer join table2)a where a.url like (concat('%',a.phrase,'%')
Not sure about more current versions, but I've run into a similar problem... the primary issue is that Hive only supports equi-join statements... when you apply logic to either side of the join, it has difficulty translating into a Map Reduce function.
The alternative method, if you have a reliably structured field, is that you can create a matching key from the larger field. For example, if you know that you're looking for your keyword to exist in the second position of a dot-delimited URI, you could do something like:
select
Uri
, split(Uri, "\\.")[1] as matchKey
from
Table1
join Table2 on Table2.keyword = Table1.matchKey
;

NOT IN query... odd results

I need a list of users in one database that are not listed as the new_user_id in another. There are 112,815 matching users in both databases; user_id is the key in all queries tables.
Query #1 works, and gives me 111,327 users who are NOT referenced as a new_user_Id. But it requires querying the same data twice.
-- 111,327 GSU users are NOT listed as a CSS new user
-- 1,488 GSU users ARE listed as a new user in CSS
--
select count(gup.user_id)
from gsu.user_profile gup
join (select cud.user_id, cud.new_user_id, cud.user_type_code
from css.user_desc cud) cudsubq
on gup.user_id = cudsubq.user_id
where gup.user_id not in (select cud.new_user_id
from css.user_desc cud
where cud.new_user_id is not null);
Query #2 would be perfect... and I'm actually surprised that it's syntactically accepted. But it gives me a result that makes no sense.
-- This gives me 1,505 users... I've checked, and they are not
-- referenced as new_user_ids in CSS, but I don't know why the ones
-- that were excluded were excluded.
--
-- Where are the missing 109,822, and whatexcluded them?
--
select count(gup.user_id)
from gsu.user_profile gup
join (select cud.user_id, cud.new_user_id, cud.user_type_code
from css.user_desc cud) cudsubq
on gup.user_id = cudsubq.user_id
where gup.user_id not in (cudsubq.new_user_id);
What exactly is the where clause in the second query doing, and why is it excluding 109,822 records from the results?
Note The above query is a simplification of what I'm really after. There are other/better ways to do the above queries... they're just representative of the part of the query that's giving me problems.
Read this: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:442029737684
For what I understand, your cudsubq.new_user_id can be NULL even though both tables are joined by user_id, so, you won't get results using the NOT IN operator when the subset contains NULL values . Consider the example in the article:
select * from dual where dummy not in ( NULL )
This returns no records. Try using the NOT EXISTS operator or just another kind of join. Here is a good source: http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
And what you need is the fourth example:
SELECT COUNT(descr.user_id)
FROM
user_profile prof
LEFT OUTER JOIN user_desc descr
ON prof.user_id = descr.user_id
WHERE descr.new_user_id IS NULL
OR descr.new_user_id != prof.user_id
Second query is semantically different. In this case
where gup.user_id not in (cudsubq.new_user_id)
cudsubq.new_user_id is treated as expression (doc: IN condition), not as a subquery, thus the whole clause is basically equivalent to
where gup.user_id != cudsubq.new_user_id
So, in your first query, you're literally asking "show me all users in GUP, who also have entries in CSS and their GUP.ID is not matching ANY NOT NULL NEW_ID in CSS ".
However, the second query is "show me all users in GUP, who also have entries in CSS and their GUP.ID is not equal to their RESPECTIVE NULLABLE (no is not null clause, remember?) CSS.NEW_ID value".
And any (not) in (or equality/inequality) checks with nulls don't actually work.
12:07:54 SYSTEM#oars_sandbox> select * from dual where 1 not in (null, 2, 3, 4);
no rows selected
Elapsed: 00:00:00.00
This is where you lose your rows. I would probably rewrite your second query's where clause as
where cudsubq.new_user_id is null, assuming that non-matching users have null new_user_id.
Your second select compares gup.user_id with cud.new_user_id on current joining record. You can rewrite the query to get the same result
select count(gup.user_id)
from gsu.user_profile gup
join (select cud.user_id, cud.new_user_id, cud.user_type_code
from css.user_desc cud) cudsubq
on gup.user_id = cudsubq.user_id
where gup.user_id != cud.new_user_id or cud.new_user_id is null;
You mentioned you compare list of user in one database with a list of users in another. So you need to query data twice and you don't query the same data. Maybe you can use "minus" operator to avoid using "in"
select count(gup.user_id)
from gsu.user_profile gup
join (select cud.user_id from css.user_desc cud
minus
select cud.new_user_id from css.user_desc cud) cudsubq
on gup.user_id = cudsubq.user_id;
You want new_user_id's from table gup that don't match any new_user_id on table cud, right? It sounds like a job for a left join:
SELECT count(gup.user_id)
FROM gsu.user_profile gup LEFT JOIN css.user_desc cud
ON gup.user_id = cud.new_user_id
WHERE cud.new_user_id is NULL
The join keeps all rows of gup, matching them with a new_user_id if possible. The WHERE condition keeps only the rows that have no matching row in cud.
(Apologies if you know this already and you're only interested in the behavior of the not in query)

Efficient Alternative to Outer Join

The RIGHT JOIN on this query causes a TABLE ACCESS FULL on lims.operator. A regular join runs quickly, but of course, the samples 'WHERE authorised_by IS NULL' do not show up.
Is there a more efficient alternative to a RIGHT JOIN in this case?
SELECT full_name
FROM (SELECT operator_id AS authorised_by, full_name
FROM lims.operator)
RIGHT JOIN (SELECT sample_id, authorised_by
FROM lims.sample
WHERE sample_template_id = 200)
USING (authorised_by)
NOTE: All columns shown (except full_name) are indexed and the primary key of some table.
Since you're doing an outer join, it could easily be that it actually is more efficient to do a full table scan rather than use the index.
If you are convinced the index should be used, force it with a hint:
SELECT /*+ INDEX (lims.operator operator_index_name)*/ ...
then see what happens...
No need to nest queries. Try this:
select s.full_name
from lims.operator o, lims.sample s
where o.operator_id = s.authorised_by(+)
and s.sample_template_id = 200
I didn't write sql for oracle since a while, but i would write the query like this:
SELECT lims.operator.full_name
FROM lims.operator
RIGHT JOIN lims.sample
on lims.operator.operator_id = lims.sample.authorized_by
and sample_template_id = 200
Does this still perform that bad?

Resources