Outer Join in mYsql Qyery - mysql

I have folowing MYsql Query And Trying to right outer join but unable to understan how to do this
here is query plase any one help
select lp_des.lpname,today.cnt_veh_tdy,todate.cnt_veh_tdate
from
(select distinct registration.lpcode,loadingpoint.lpname
from registration,loadingpoint
where registration.lpcode=loadingpoint.lpcode) lp_des,
(select lpcode,count(vehicleno) cnt_veh_tdate
from registration
where registration.companycode='01'
group by lpcode) todate,
(
select lpcode,count(vehicleno) cnt_veh_tdy
from registration
where registration.companycode='01'
and registration.date=(select max(date) from registration)
group by lpcode) today
right outer join today on lp_des.lpcode = today.lpcode
right outer join todate on lp_des.lpcode = todate.lpcode
I want to make right outer join on this part
where lp_des.lpcode=todate.lpcode
and lp_des.lpcode=today.lpcode
Please help and Thanks in advance

You asked for this:
select
lp_des.lpname,
today.cnt_veh_tdy,
todate.cnt_veh_tdate
from
(select distinct
r.lpcode,
l.lpname
from
registration r
inner join loadingpoint l on l.lpcode = r.lpcode) lp_des
right join
(select
r.lpcode,
count(r.vehicleno) cnt_veh_tdate
from
registration r
where
r.companycode='01'
group by
lpcode) todate on todate.lpcode = lp_des.lpcode
right join
(select
r.lpcode,
count(r.vehicleno) cnt_veh_tdy
from
registration r
where
r.companycode = '01'
and registration.date = (select max(date) from registration)
group by
r.lpcode) today on today.lpcode = lp_des.lpcode
But I think you mean this:
select
r.lpcode,
l.lpname,
count(r.vehicleno) cnt_veh_tdate,
count(case when r.date = md.date then r.vehicleno else null end) cnt_veh_tdy
from
registration r
inner join (select max(rm.date) maxdate from registration rm) md
left join loadingpoint l on l.lpcode = r.lpcode
where
r.companycode = '01'
group by
r.lpcode
and maybe even this:
select
r.lpcode,
l.lpname,
count(r.vehicleno) cnt_veh_tdate,
count(case when r.date = date() then r.vehicleno else null end) cnt_veh_tdy
from
registration r
left join loadingpoint l on l.lpcode = r.lpcode
where
r.companycode = '01'
group by
r.lpcode
If I read it correctly, you want a query that returns the number of vehicles for company 1 assigned to a loading point, overall as well as for today only. And you also want that count for vehicles that do not have loading point assigned yet.
Though it would help if you would have added this description. It will help the ones answering your question, but it will also help you writing the right query in the first place.

The syntax for a right outer join is:
SELECT t1.id, t2.id FROM t1 RIGHT OUTER JOIN t2 ON t1.field1 = t2.field2
If you're joining on the same field you can use USING instead of ON:
SELECT t1.id, t2.id FROM t1 RIGHT OUTER JOIN t2 USING (field)

Related

How can i Get Better Time Result on This Mysql Query

i am Using This Mysql Query and is working Good, But i need go get a Better Time result. How can i do it?
SELECT TblExistencias.id as ID, TblExistencias.codigo as Codigo,
TblPartes.detalle as Detalle,TblPartes.neto1 as PrecioActual,
TblExistencias.Condicion_Producto as Condicion,TblCategorias.categoria as Categoria,
TblSubcategorias.subcategoria as Subcategoria, TblExistencias.costo as Costo,
TblExistencias.serial as Serial, TblExistencias.vendido as Vendido,
TblConceptosFacturas.ventaonline as VentaOnline, TblRemitos.nroremitocompleto as Remito,
TblFacturas.nrofacturacompleto as Factura, TblFacturas.fecha as FechaVenta,
TblConceptosFacturas.ventaTotUn as Venta,TblConceptosFacturas.comisionmlunit as Comision,
TblFacturas.costoenvio as Envio, if(TblExistencias.vendido =1,
TblConceptosFacturas.ventaTotUn - TblExistencias.Costo - TblConceptosFacturas.comisionmlunit - TblFacturas.costoenvio,0) as Ganancia,
TblProveedores.razonsocial as Proveedor, TblFacturasCompras.nrofacturacompleto as Compra,
TblFacturasCompras.fecha as FechaCompra, TblClientes.razonsocial as Cliente
from TblExistencias
left join TblPartes on TblExistencias.codigo = TblPartes.codigo1
left join TblRemitos on TblExistencias.id_RemitoVenta = TblRemitos.id
left join TblFacturasCompras on TblExistencias.id_factura = TblFacturasCompras.id
left join TblClientes on TblRemitos.id_cliente = TblClientes.id
left join TblFacturas on TblRemitos.id_factura = TblFacturas.id
left join TblConceptosFacturas on TblFacturas.id=TblConceptosFacturas.id_factura and TblConceptosFacturas.codigoproducto = TblExistencias.codigo
left join TblCategorias on TblCategorias.id = TblPartes.id_categoria
left join TblSubcategorias on TblPartes.id_subcategoria = TblSubcategorias.id
left join TblProveedores on TblFacturasCompras.id_proveedor = TblProveedores.id
order by comision desc
The solution is create an index on each relational columns, like:
TblFacturasCompras.id_proveedor = TblProveedores.id
Problem was in order clause, Query passed from 87 Secs to 4 Secs. Thanks for help.

How to show the repeated value as NULL in sql?

I have a query which gives result as below, how to replace duplicate values with NULL
Query:
SELECT
word.lemma,
synset.definition,
synset.pos,
sampletable.sample
FROM
word
LEFT JOIN
sense ON word.wordid = sense.wordid
LEFT JOIN
synset ON sense.synsetid = synset.synsetid
LEFT JOIN
sampletable ON synset.synsetid = sampletable.synsetid
WHERE
word.lemma = 'good'
Result:
Required Result: all the greyed out results as NULL
First, this is the type of transformation that is generally better done at the application level. The reason is that it presupposes that the result set is in a particular order -- and you seem to be assuming this even with no order by clause.
Second, it is often simpler in the application.
However, in MySQL 8+, it is not that hard. You can do:
SELECT w.lemma,
(CASE WHEN ROW_NUMBER() OVER (PARTITION BY w.lemma, ss.definition ORDER BY st.sample) = 1
THEN ss.definition
END) as definition,
ss.pos,
st.sample
FROM word w LEFT JOIN
sense s
ON w.wordid = s.wordid LEFT JOIN
synset ss
ON s.synsetid = ss.synsetid LEFT JOIN
sampletable st
ON ss.synsetid = st.synsetid
WHERE w.lemma = 'good'
ORDER BY w.lemma, ss.definition, st.sample;
For this to work reliably, the outer ORDER BY clause needs to be compatible with the ORDER BY for the window function.
If you are using Mysql 8 try with Rank().. As I didn't have your table or data couldn't test this query.
SELECT
word.lemma
,case when r = 1 synset.definition else null end as definition
,synset.pos
,sampletable.sample
FROM
(
SELECT
word.lemma
,synset.definition
,synset.pos
,sampletable.sample
,RANK() OVER (PARTITION BY synset.definition ORDER BY synset.definition) r
FROM
(
SELECT
word.lemma,
synset.definition,
synset.pos,
sampletable.sample
FROM
word
LEFT JOIN
sense ON word.wordid = sense.wordid
LEFT JOIN
synset ON sense.synsetid = synset.synsetid
LEFT JOIN
sampletable ON synset.synsetid = sampletable.synsetid
WHERE
word.lemma = 'good'
) t
)t1;

Count based on another count - MySQL

I have the following Set of tables and I want to get all the services, age ranges and genders and next to each three of them the count of recipients corresponding to them.
So far I came up with the statement below, and it works.
select s.service_name,s.service_id,g.gender_id,ag.age_range_id,count(r.recipient_id) Temp
from tbl_services s inner join tbl_gender g
inner join tbl_age_range ag
left join tbl_recipient_services rs on rs.service_id=s.service_id
left join tbl_recipient r on r.gender_id=g.gender_id and rs.recipient_id=r.recipient_id
and (year(sysdate())-year(r.recipient_birth_date) >= min_age and year(sysdate())-year(r.recipient_birth_date) <= max_age)
group by s.service_id,g.gander_id,ag.age_range_id
But I need to only count the recipients who have 2 or more services in the tbl_recipient_services and I'm stuck again.
Anyone has an idea to fix that?
First, your query would be clearer with cross joins:
select s.service_name, s.service_id, g.gender_id, ag.age_range_id,
count(r.recipient_id) as all_recipients
from tbl_services s cross join
tbl_gender g cross join
tbl_age_range ag left join
tbl_recipient_services rs
on rs.service_id = s.service_id left join
tbl_recipient r
on r.gender_id = g.gender_id and
rs.recipient_id = r.recipient_id and
year(sysdate()) - year(r.recipient_birth_date) >= min_age and
year(sysdate()) - year(r.recipient_birth_date) <= max_age)
group by s.service_id, g.gender_id, ag.age_range_id;
This returns all combinations of service/gender/age even if there are no matches.
Let's add another column. To do so, we'll use a subquery to count the number of services per recipient and then include that in the count:
select s.service_name, s.service_id, g.gender_id, ag.age_range_id,
count(r.recipient_id) as num_recipients,
sum(rs2.num_services >= 2) as num_recipients_2plus
from tbl_services s cross join
tbl_gender g cross join
tbl_age_range ag left join
tbl_recipient_services rs
on rs.service_id = s.service_id left join
tbl_recipient r
on r.gender_id = g.gender_id and
rs.recipient_id = r.recipient_id and
year(sysdate()) - year(r.recipient_birth_date) >= min_age and
year(sysdate()) - year(r.recipient_birth_date) <= max_age) left join
(select rs2.recipient_id, count(*) as num_services
from tbl_recipient_services rs2
group by rs2.recipient_id
) rs2
on rs2.recipient_id = r.recipient_id
group by s.service_id, g.gender_id, ag.age_range_id;
If you don't want the additional column, you can change the left joins to inner joins and remove the count(r.recipient_id).

SQL query wrong result

i have this query:
SELECT `completed`.`ID` AS `ID`,`completed`.`level` AS `level`,`completed`.`completed_in` AS `completed_in`, COUNT(1) AS `right_answers_num`
FROM `completed`
INNER JOIN `history` ON `history`.`ID` = `completed`.`ID`
INNER JOIN `questions` ON `questions`.`ID` = `history`.`question`
WHERE `completed`.`student_id` = '1' AND `questions`.`answer` = `history`.`answer`
GROUP BY `completed`.`ID`
ORDER BY `completed`.`completed_in` DESC
what i need is to get info of each test in completed table (id,level,completed_in,right_answer_num)
the problem with that query is that if there is no one right answer(history.answer = questions.answer) then it doesn't return the row, while it should return the row(id,level,completed_in) and the right_answer_num(counter) should be zero..
please help me,, thanks ahead.
SELECT
completed.ID AS ID,
completed.level AS level,
completed.completed_in AS completed_in,
COUNT(questions.answer) AS right_answers_num
FROM completed
INNER JOIN history ON history.ID = completed.ID
LEFT JOIN questions ON questions.ID = history.question AND questions.answer = history.answer
WHERE
completed.student_id = '1'
GROUP BY
completed.ID
ORDER BY completed.completed_in DESC
use a LEFT OUTER JOIN intead of an INNER JOIN.
The second inner join is what's causing rows with no record in the questions table to be omitted. An inner join will only return rows that have data in all corresponding tables. Change the second inner join to a left join like so:
SELECT
completed.ID AS ID,
completed.level AS level,
completed.completed_in AS completed_in,
COUNT(questions.answer) AS right_answers_num
FROM completed
INNER JOIN history ON history.ID = completed.ID
LEFT JOIN questions ON questions.ID = history.question
WHERE completed.student_id = 1
GROUP BY completed.ID
ORDER BY completed.completed_in DESC

SQL returns incorrect data using 2 left joins

I have written a MYSQL script, that returns incorrect data. I am quite fluent in SQL, but this query is not returning correct results. Can someone have a look and see whats going on. The problem is the noOfBids, and noOfRatedTimes. The values are the same for both columns and are large values too.
select
a.user_name as userName,
coalesce(count(b.sp_user_name),0) as noOfBids,
coalesce(ROUND(AVG(b.a_amount),2),0) as avgAmount,
coalesce(count(d.sp_user_name),0) as noOfRatedTimes,
coalesce(ROUND(AVG(d.user_rate),2),0)
from users a
left join project_imds b
on b.sp_user_name = a.user_name
left join projects c
on b.project_code = c.project_code
left join sp_user_rating d
on d.sp_user_name = b.sp_user_name
where a.user_type = 'SP'
and a.active = 'Y'
group by a.user_name
order by coalesce(ROUND(AVG(d.user_rate),2),0) desc;
I have created a workaround on this, by creating a temp table to get the avg values and joining this to the main query.
Since I don't know the specifics of the data behind your query, this is only a guess. But perhaps you'd rather join "sp_user_rating" directly to "users", changing
left join sp_user_rating d
on d.sp_user_name = b.sp_user_name
to
left join sp_user_rating d
on d.sp_user_name = a.user_name
select
a.user_name as userName,
coalesce(count(b.sp_user_name),0) as noOfBids,
coalesce(ROUND(AVG(b.a_amount),2),0) as avgAmount,
coalesce(count(d.sp_user_name),0) as noOfRatedTimes,
coalesce(ROUND(AVG(d.user_rate),2),0)
from users as a
left join project_imds as b
on b.sp_user_name = a.user_name
left join projects as c
on b.project_code = c.project_code
left join sp_user_rating as d
on d.sp_user_name = b.sp_user_name
where a.user_type = 'SP'
and a.active = 'Y'
group by a.user_name
order by coalesce(ROUND(AVG(d.user_rate),2),0) desc;