How to user whereIn with array having null value(conditionally) - laravel

I am new to Laravell and sql , I will have two scenarios both depends on user input
and this column may have null value so final array will looks like
DB Data
col1 col2
abc xyz
abc2 xyz2
null null
abc3 xyz3
Scenario1 :
col1 = ["abc","abc2","abc3"];
col2 = ["xyz","xyz2","xyz3"];
Scenario1 :
col1 = ["abc","abc2","abc"];
col2 = ["xyz","xyz2",null];
MY query is based on user input , for example col1 can be empty i.e null and col2 i.e null
I am using this query :
$query->whereIn( $field, $col1);
$query->whereIn( $field2, $col2);
for scenario 1 :
every thing works fine
col1 col2
abc xyz
abc2 xyz2
abc3 xyz3
for scenario 1 :
not working with null
col1 col2
empty
and with this query
$query->whereIn( $field, $col1);
$query->orWhereNull($field)
$query->whereIn( $field2, $col2);
$query->orWhereNull($field2)
no results
can any one guide me in the right direction how can i have the results with null also
and FYI its AND query i.e filter col1 && col2

I can test it right now, but you need to separate your statement.
Something like :
$query->whereHas($field, function ($query) use ($field, $col1) {
if (in_array(null, $col1)) {
$query->whereNull($field)->orWhereIn($field, $col1);
} else {
$query->whereIn($field, $col1);
}
});
$query->whereHas($field2, function ($query) use ($field2, $col2) {
if (in_array(null, $col2)) {
$query->whereNull($field2)->orWhereIn($field2, $col2);
} else {
$query->whereIn($field2, $col2);
}
});

Related

Laravel query where In with empty array clasue

I have array like this
$ans = [1,2,3];
$ans2 = [5, 4]
$ans3 = [6,7];
Syntax 1 :
$query->whereIn($field , $ans);
$query->whereIn($field1 , $ans2);
$query->whereIn($field2 , $ans3); //problem is here when array
//has null value it doesnt work as expected
so query is something like
select * from table
where field in (1,2,3)
and field1 in (5,4)
and field2 in (6,7)
result is correct because it is doing and for all field && field1 && field2
but when input has null it didn't work as expected
$ans = [1,2,3];
$ans2 = [5, 4]
$ans3 = [6,null];
now my query is
first solution
$query->whereIn($field , $ans);
$query->whereIn($field1 , $ans2);
$query->whereIn($field2 , $ans3); //problem is here when array has null value
it doesnt work as expected
this dont work as we have null in feild3 so result is []
$query->whereIn($field , $ans);
$query->whereIn($field1 , $ans2);
$searchArray = collect($field2)->filter()->all();//filter array having null values
$query->whereIn($field2, $searchArray)
$query->where($field2 , null);
so query becomes something like this
select * from table
where field in (1,2,3)
and field1 in (5,4)
and field2 in (6)
and field2 is null //wrong as field should have or in null case because i want to get field2 having 6 or null
that leads me to this
$query->whereIn($field , $ans);
$query->whereIn($field1 , $ans2);
$searchArray = collect($field2)->filter()->all();//filter array having null values
$query->whereIn($field2, $searchArray)
->orWhereNull($field2);
result is field2 having 6 and also null but not it dont take care of other fields query is like
select * from table
where field in (1,2,3)
and field1 in (5,4)
and field2 in (6)
or field2 is null //it always show results with null and 6
// but field1 and field2 are not matter are neglected
i want something like this may be this is the right approach
select * from table
where field in (1,2,3)
and field1 in (5,4)
and (field2 in (6)
or field2 is null) //extra parenthesis so field 2 should have 6 or null but it should **and** field1, field2
any hint how i can achieve filed2 when has null and a value i.e [null, 6] should do something like this
(1 ,2,3 ) && (5,4) && (6 || null)
You can use a callback in where clause
Like:
$query->where(function($q) use ($field2, $searchArray) {
$q->whereIn($field2, $searchArray)->orWhereNull($field2);
});
Make a subquery, change :
$query->where($field2 , null);
to,
$query->where('field2', function($q) use($ans3){
$q->whereIn('field2', $ans3)
->orWhereNull('field2')
})
Why not try removing/unsetting the null key before passing the array into the where query,
if array_filter($field2); doesn't work correctly
try this post Remove empty array elements

Oracle - Delete records with conditions

I would like to write SQL which deletes records based on a few conditions.
I have four records
In these records, ID is unique and can change. Name is used to delete the records.
1) A Name should have at least one OK type.
2) IF Name has an ID that doesn't contain DUMMY in its name, then delete all other records where ID contains DUMMY.
How can I do this in SQL?
Try this:
delete from tablename t
where t."id" like '%DUMMY%'
and t."name" = (
select "name" from tablename
where "name" = '?'
group by "name"
having sum(case when "type" = 'OK' then 1 else 0 end) > 0
and sum(case when "id" not like '%DUMMY%' then 1 else 0 end) > 0
)
The subquery after the IN clause returns the names that have at least 1 type = 'OK' and at least 1 id not containing 'DUMMY'.
Edit:
delete from tablename t
where
t."name" = '?'
and (
(t."id" like '%DUMMY%' and t."type" <> 'OK')
or (
t."type" = 'OK'
and exists (
select 1 from tablename
where "name" = t."name" and "type" = t."type" and "id" > t."id"
)
)
)

Pig latin programming

I have a table loaded in a variable in pig whose schema looks like this:
What I want to accomplish through a pig-latin script is to populate the value "JKL", "PQR" and so on.. in col 4 that is blank for the rest of the rows. The blank rows must copy only the values in the previous cell in the col 4. Check the example below.
The target table should like this:
if your requirement is to update Col4 value to XYZ for all the records which are having values null or empty then you can use the following code snippet to do the same
--Load input data
input_data = LOAD 'input.txt' USING PigStorage() AS (Col1:chararray, Col2:int, Col3:int, Col4:chararray);
--Perform operation on each record
input_data = FOREACH input_data GENERATE Col1, Col2, Col3, ((Col4 is null or TRIM(Col4) == '') ? 'XYZ' : Col4) as Col4;
here assuming that you are holding your input_data then for each record check whether the Col4 value is null or empty, if it is then update it with the desired value (XYZ) or else just use the existing value
Is the Col1 is same for all the rows. If Yes, then Use two set of Filter else u have to find the uniq value between col1 & Col4 and remove the NULL value thn use below steps
Filter_One will capture Col1 & Col4 where Col4 is not NULL
Filter_Two will capture Col1, Col2, Col3. Use Join Filter_one &
Filter_Two, where Filter_two will be printed 1st, 2nd , 3rd Column
and Filter_one 2nd Column will be pronted at 4th Position,
hope the same will help
The Pig script will be like :
Filter_one = foreach Load_Data generate $0 as col1, $3 as col4;
Filter_one_temp = filter Filter_one by ($1 is not null);
Filter_two = foreach Load_Data generate $0 as col1, $1 as col2, $2 as col3;
Join_filter = JOIN Filter_two by $0 LEFT, Filter_one_temp by $0;
generetate_output = foreach Join_filter generate $0 as col1, $1 as col2 , $2 as col3,$4 as col4;
store generetate_output into 'dfs_path' using PigStorage(',');
as am storing the same with , delimeter so the output will be like
(ABC,34,23,XYZ)
(ABC,12,78,XYZ)
(ABC,4,21,XYZ)
(ABC,22,54,XYZ)
(DEF,32,455,JKL)
(DEF,21,45,JKL)
(DEF,45,687,JKL)
(DEF,232,565,JKL)
(DEF,23,32,JKL)

PreparedStatement and 'null' value in WHERE clause

I am using PrepareStatement and BatchUpdate for executimg a UPDATE query. In for loop I create a Batch. At end of loop I execute batch.
Above logic works fine if SQL query used in PrepareStatement does not have null values in WHERE claues.
Update Statement fails if there is null value in WHERE clasue.
My code looks something like this,
connection = getConnection();
PreparedStatement ps = connection.prepareStatement(
"UPDATE TEST_TABLE SET Col1 = true WHERE Col2 = ? AND Col3 = ?");
for (Data aa : InComingData){
if(null == aa.getCol2()){
ps.setNull(1, java.sql.Types.INTEGER);
}
else {
ps.setInteger(1,aa.getCol2())
}
if(null == aa.getCol3()) {
ps.setNull(2, java.sql.Types.INTEGER);
}
else {
ps.setInteger(2,aa.getCol3())
}
ps.addBatch();
}
ps.executeBatch();
connection.commit();
Any help would be appreciated.
If you do not wish to generate SQL dynamically, you may use NVL on all the nullable columns in your WHERE clause to convert null into some value that the column will never contain; and while setting the bind variables in Statement just convert null to the same value used in NVL function. For example,
String sql = "UPDATE TEST_TABLE SET Col1 = true
WHERE NVL(Col2, -1) = ? AND NVL(Col3, -1) = ?";
And in Statement:
ps.setInt(1, aa.getCol2() == null ? -1 : aa.getCol2().intValue());
ps.setInt(2, aa.getCol3() == null ? -1 : aa.getCol3().intValue());
That's because in SQL, something = null is always false, even if something is null. To compare a column with null, you must use where col2 is null, instead of where col2 = null.

Linq and sorting null fields

I have a table that has (for example) 4 columns.
pk_table_id INT NOT NULL
username VARCHAR(100) NOT NULL
start_date DATETIME NOT NULL
end_date DATETIME NULL
My requirement is to return all rows in descending order of end_date - BUT the NULL values must be first, and then descending order of start_date.
I've done it in SQL - but could someone assist me with a LINQ version to do this?
This is the SQL query we use:
SELECT [person_employment_id]
, [party_id]
, [employer_name]
, [occupation]
, [telephone]
, [start_date]
, [end_date]
, [person_employment_type_id]
, [person_employment_end_reason_type_id]
, [comments]
, [deleted]
, [create_user]
, [create_date]
, [last_update_user]
, [last_update_date]
, [version]
FROM [dbo].[person_employment]
WHERE ([party_id]=#party_id)
ORDER BY ISNull([end_date],'9999-DEC-31') DESC, [start_date] DESC
For this problem, you could do a null check on the end_date and use that result as the ordering. So you don't need to use the same SQL constructs to achieve this, but rather use one more natural in your language of choice (C# I'm assuming).
var query =
from row in dc.Table
let isEndDateNull = row.end_date == null
orderby isEndDateNull descending, row.start_date descending
select row;

Resources