Problem to convert a SQL query to an Laravel Query Builder - sql

I want to convert this SQL Query to LAravel SQL Builder but i don't know why I already read the laravel documentation but I can't find the answer
SQL Query:
SELECT
CONTRATO,
CASE WHEN RAZONSOCIAL IS NULL OR RAZONSOCIAL = ''
THEN ISNULL(PATERNO, '') + ' ' + ISNULL(MATERNO, '') + ' ' + ISNULL(NOMBRES, '')
ELSE RAZONSOCIAL
END AS NOMBRE,
CADENAUNICA,
CLAVERASTREO,
FECHAASIENTO,
IDGARANTIA,
RutaGuardadoPDF,
RutaGuardadoXML
FROM
DEUDORES AS D
LEFT JOIN
RELACIONES AS R
ON D.RUGID = R.RUGID
WHERE CONTRATO = 'A1412015'
AND D.AcreedorId IN (
SELECT
ACREEDORID
FROM
[MasterCLI].[dbo].[Rrug]
WHERE FIDEICOMISOID = 5
)
and i do this code in laravel
$AcreedorFide = \DB::connection('sqlsrv')
->table('Rrug')
->select('AcreedorID')
->where('Fideicomiso', $fideicomiso)
->get();
$BoletaRUG = \DB::connection('RUG')
->table('Deudores')
->select(
'Contrato',
'CadenaUnica',
'ClaveRastreo',
'FechaAsiento',
'IdGarantia',
'RutaGuardadoPDF',
'RutaGuardadoXML'
)
->select(DB::raw('CASE WHEN RAZONSOCIAL IS NULL'))
->leftJoin('Relaciones','Deudores.RugId', '=', 'Relaciones.RugId')
->where('Contrato', $Contrato)
->wherein('Acreedorid', $AcreedorFide)
->get();

The most SQL-like way of remaking this query in the Query Builder is the following:
DB::connection('sqlsrv')->query()
->select(
'CONTRATO',
'CADENAUNICA',
'CLAVERASTREO',
'FECHAASIENTO',
'IDGARANTIA',
'RutaGuardadoPDF',
'RutaGuardadoXML'
)
->selectRaw(
"CASE WHEN RAZONSOCIAL IS NULL OR RAZONSOCIAL = '' ".
"THEN ISNULL(PATERNO, '') + ' ' + ISNULL(MATERNO, '') + ' ' + ISNULL(NOMBRES, '') ".
"ELSE RAZONSOCIAL ".
"END AS NOMBRE"
)
->from('DEUDORES', 'D')
->leftJoin('RELACIONES AS R', 'D.RUGID', '=', 'R.RUGID')
->where('CONTRATO', '=', 'A1412015')
->whereIn('D.AcreedorId', function ($query) {
$query->select('ACREEDORID')
->from('MasterCLI.dbo.Rrug')
->where('FIDEICOMISOID', '=', 5);
})
->get();
For anyone stuck on translating queries, as the comments have stated, the easiest way to remake large, complex-looking queries in the builder is by dumping the query using ->toSql() instead of ->get() and checking if it's missing something or not. Trial and error.
My personal advice is to start from the subqueries and work your way up. Also, Some differences/shorthands:
Instead of DB::connection(...)->query()->select(...)->from('DEUDORES', 'D')->where(...),you can specify the main table you're querying first:DB::connection(...)->table('DEUDORES', 'D')->select(...)->where(...)
If the comparison operator is '=' you can leave it implied. In this example:
leftJoin('RELACIONES AS R', 'D.RUGID', '=', 'R.RUGID') becomes leftJoin('RELACIONES AS R', 'D.RUGID', 'R.RUGID')
where('CONTRATO', '=', 'A1412015') becomes where('CONTRATO', 'A1412015')
If you use the same connection as the default one (DB_CONNECTION in your .env file), you can skip the connection(...) in the queries. DB::connection(...)->table(...) becomes DB::table(...).

Related

Remove html tags from a column

I have the a column in my table which stores a paragraph like below :
<p>I like it.</p>this is my job.<main>current.</main>
I want to remove the tags <p>, </p>, and and all tags between < and >.
So my expected output will be like below :
I like it. this is my job. current.
please try this
DECLARE #txt NVARCHAR(MAX) = '<p>I like it.</p>this is my job.<main>current.</main>'
SELECT x.value('.', 'NVARCHAR(MAX)') FROM ( SELECT x =
CAST(REPLACE(REPLACE(#txt, '>', '/>'), '</', '<') AS XML) ) r
this will help to remove all tags
UPDATE: Samir's answer is better than mine as it can deal with html-crap
(as long as there is no < or > as normal content :-)
You can try this:
If your string is valid XML (meaning XHTML) you might go this route:
DECLARE #yourString NVARCHAR(100)=N'<p>I like it.</p>this is my job.<main>current.</main>';
SELECT CAST(#yourString AS XML).value('.','nvarchar(max)');
returns
I like it.this is my job.current.
Using . as the XPath will return the whole content as is...
Any invalid XML (very likely with simple html) will break this...
You can use giant REPLACE() :
SELECT REPLACE(REPLACE(REPLACE(REPLACE(col, '<p>', ''), '</p>', ''), '<main>, ''), '</main>', '')
If you are working the latest SQL version then this will be easy to write using TRANSLATE() :
SELECT TRANSLATE(col, '<p></p><main></main>', '')
If u want remove tags when select, you can do a normal SELECT and clear string:
SELECT column FROM my_table;
$value = $row["column"];
$value_replaced = str_replace('<p>', '', $value);
$value = $value_replaced;
$value_replaced = str_replace('</p>', '', $value);
$value = $value_replaced;
$value_replaced = str_replace('<main>', '', $value);
$value = $value_replaced;
$value_replaced = str_replace('</main>', '', $value);

LINQ Query to search for users with partial name

I have this SQL query:
SELECT
*
FROM
employeeTable
WHERE
(
concat(first_name, ' ', last_name) like concat('%', replace(#MatchString, ' ', '%'), '%')
or
concat(last_name, ' ', first_name) like concat('%', replace(#MatchString, ' ', '%'), '%')
)
It works perfectly by searching both name and last name with partial values., by searching users with partial strings. So for example:
"ric jon" will find Rick Jones, Richard Jonesy, and Jonathan Prichter.
I have the following Linq Query, using Entity Framework:
from employee in context.Employee
where employee.first_name.Contains(matchString)
|| employee.last_name.Contains(matchString)
select employee
But the string "ric jon" does not find anything.
I can't seem to make that linq query work the same as the SQL query.
That SQL wouldn't in fact find those records you sampled with the given "ric jon". What you are asking for is a special filter which IMHO requires a function that is not natively supported by the backend (you didn't specify your backend but anyway at least I don't know a backend that would support this natively). Something like this would work (note that you are getting the Employee records to local, this is not done at backend level):
Func<Employee, string[], bool> match = (emp, _parts) => {
return
((emp.FirstName.IndexOf(_parts[0],StringComparison.CurrentCultureIgnoreCase ) != -1) &&
(_parts.Length == 1 || emp.LastName.IndexOf(_parts[1], StringComparison.CurrentCultureIgnoreCase) != -1)) ||
((_parts.Length == 1 || emp.FirstName.IndexOf(_parts[1], StringComparison.CurrentCultureIgnoreCase) != -1) &&
(emp.LastName.IndexOf(_parts[0], StringComparison.CurrentCultureIgnoreCase) != -1));
};
string search = "ric jon";
var result = context.Employee.AsEnumerable()
.Where(n => match(n, search.Split()));
Update:
You can use this one which would be supported by many backends:
string search = "ric jon";
string[] parts = search.ToLowerInvariant().Split();
string p1 = parts.Length < 1 ? "" :parts[0];
string p2 = parts.Length < 2 ? "" :parts[1];
var result = context.Employee.Where(n =>
((n.FirstName.ToLowerInvariant().Contains(p1) &&
n.LastName.ToLowerInvariant().Contains(p2))) ||
((n.FirstName.ToLowerInvariant().Contains(p2) &&
n.LastName.ToLowerInvariant().Contains(p1))));

QueryBuilder and inner join

Here is the request :
select concat(user.nom, ' ', user.prenom), trace.action
from MyBundle:Ttrace trace
innerjoin MyBundle:User user on user.id = trace.user
where trace.datfin is null
Can somebody translate that using queryBuilder ?
Thank you
I tried this but it does not work :
$this->getEntityManager()->createQueryBuilder()
->select("trace.action")
->addSelect("concat(user.nom, ' ', user.prenom)")
->from('MyBundle:Ttrace', 'trace')
->innerjoin('trace', 'MyBundle:User', 'user', 'user.id = trace.user')
->where('trace.datfin is null');
But it does not work.
I also tried :
$this->getEntityManager()->createQueryBuilder()
->select("trace.action")
->addSelect("concat(user.nom, ' ', user.prenom)")
->from('MyBundle:Ttrace', 'trace')
->join('MyBundle:User', 'user')
->where('trace.datfin is null');
but sql query is wrong with:
innerjoin user on (trace.datfin is null) NONSENSE!! and of course no where in the sql query
So, does somebody know (it is easy they say) how to build it (with a query builder)
ty
Hoping it is gonna help somebody :
$qb = $this->getEntityManager()->createQueryBuilder()
->select('trace.action')
->addSelect("concat(user.nom, ' ', user.prenom)")
->from('MyBundle:Ttrace', 'trace');
$qb->join('MyBundle:User', 'u', Join::WITH, $qb->expr()->eq('trace.user', 'u.id'));
$qb->where($qb->expr()->isNull('trace.datfin');

Laravel 5 Eloquent where and or in Clauses

i try to get results from table with multiple where and/or clauses.
My SQL statement is:
SELECT * FROM tbl
WHERE m__Id = 46
AND
t_Id = 2
AND
(Cab = 2 OR Cab = 4)
How i can get this with Laravel Eloquent?
My Code in Laravel is:
$BType = CabRes::where('m_Id', '=', '46')
->where('t_Id', '=', '2')
->where('Cab', '2')
->orWhere('Cab', '=', '4')
->get();
Using advanced wheres:
CabRes::where('m__Id', 46)
->where('t_Id', 2)
->where(function($q) {
$q->where('Cab', 2)
->orWhere('Cab', 4);
})
->get();
Or, even better, using whereIn():
CabRes::where('m__Id', 46)
->where('t_Id', 2)
->whereIn('Cab', $cabIds)
->get();
Also, if you have a variable,
CabRes::where('m_Id', 46)
->where('t_Id', 2)
->where(function($q) use ($variable){
$q->where('Cab', 2)
->orWhere('Cab', $variable);
})
->get();
When we use multiple and (where) condition with last (where + or where) the where condition fails most of the time. for that we can use the nested where function with parameters passing in that.
$feedsql = DB::table('feeds as t1')
->leftjoin('groups as t2', 't1.groups_id', '=', 't2.id')
->where('t2.status', 1)
->whereRaw("t1.published_on <= NOW()")
>whereIn('t1.groupid', $group_ids)
->where(function($q)use ($userid) {
$q->where('t2.contact_users_id', $userid)
->orWhere('t1.users_id', $userid);
})
->orderBy('t1.published_on', 'desc')->get();
The above query validate all where condition then finally checks
where t2.status=1 and
(where t2.contact_users_id='$userid' or where t1.users_id='$userid')

Laravel Eloquent Select CASE?

Is there anyone with experience in PHP & Laravel Eloquent who can help me resolve this statement? I'm trying to inject a CASE... WHEN.. END... inside a raw() method. It seemed like it was completely ignored. The existing documentation hasn't been . I've tried several different things to no prevail. I'm trying to pull this off:
SELECT shares.id, ...,
CASE WHEN users.id = <CurrentUser> THEN 1 ELSE 0 END AS is_user,
...
FROM <table>
...
The source code is below:
$shares = Share::where('shares.status', '=', SHARE_STATUS_APPROVED)
->where('shares.deleted', '=', '0')
->where('locations.lat', '<=', $nelat)
->where('locations.lat', '>=', $swlat)
->where('locations.lng', '>=', $nelng)
->where('locations.lng', '<=', $swlng)
->where('users.id', '=', $user)
->orWhere('shares.connected_user_id', '=', $user)
->join('users', 'shares.user_id', '=', 'users.id')
->join('locations', 'locations.id', '=', 'users.location_id')
->join('provinces', 'provinces.id', '=', 'locations.province_id')
->join('countries', 'countries.id', '=', 'locations.country_id')
->select('shares.id AS share_id', 'users.id AS user_id', 'shares.connected_user_id', 'shares.original_language_id', 'shares.image',
'users.first_name', 'users.last_name', 'users.email',
'locations.city', 'provinces.name', 'countries.code',
'locations.lat', 'locations.lng',
'shares.created_at')
->raw('(CASE WHEN users.id = ' . $user . ' THEN 1 ELSE 0 END) AS is_user')
->orderBy('shares.created_at', 'desc')
->orderBy('users.id', 'asc')
->orderBy('shares.connected_user_id', 'asc')
->get();
Move your raw() call inside the SELECT statement:
->select('shares.id AS share_id', 'users.id AS user_id', 'shares.connected_user_id',
'shares.original_language_id', 'shares.image',
'users.first_name', 'users.last_name', 'users.email',
'locations.city', 'provinces.name', 'countries.code',
'locations.lat', 'locations.lng',
'shares.created_at',
DB::raw('(CASE WHEN users.id = ' . $user . ' THEN 1 ELSE 0 END) AS is_user')
)
->orderBy('shares.created_at', 'desc')
From: https://laravel.com/docs/5.4/queries#raw-expressions
Alternatively you can use selectRaw instead.
->selectRaw("shares.id AS share_id, users.id AS user_id ,
shares.connected_user_id ,
shares.original_language_id, shares.image,
users.first_name, users.last_name, users.email,
locations.city, provinces.name, countries.code,
locations.lat, locations.lng,
shares.created_at,
(CASE WHEN users.id = {$user} THEN 1 ELSE 0 END) AS is_user)")
->orderBy('shares.created_at', 'desc')
Just recently I have created a package that adds CASE support for Eloquent Query Builder. You can check it out here: https://github.com/aglipanci/laravel-eloquent-case
Using the package you can do this:
use App\Models\Invoice;
use AgliPanci\LaravelCase\Query\CaseBuilder;
$invoices = Invoice::query()
->case(function (CaseBuilder $case) {
$case->when('balance', '<', 0)->then('Overpaid')
->when('balance', 0)->then('Paid')
->else('Balance Due');
}, 'payment_status')
->get();