REGEX starts by Subquery - mysql

This is a query that i just made and it works correctly
select
sum(IF(l.bandera='DEBITO',l.valor,0)) totdebito,
sum(IF(l.bandera='CREDITO',l.valor,0)) totcredito ,n.nit_ID
from lineaasiento l left join clientesam c on c.Dk=l.clientesmayor_OID
left join proveedores p on p.Dk=l.proveedor_OID left join empleado e on e.Dk=l.empleado_OID
left join banco b on b.Dk=l.banco_OID left join cuentacontable cc on cc.Dk=l.cuentacontable_OID
left join nit n on n.Dk=coalesce(c.nit_OID,p.nit_OID,e.nit_OID,b.nit_OID,null)
where (timefcontable between '2013-01-01' and '2013-12-31') and
estadolinea_OID in (Select Dk from estadoasiento where codigo!=4) and
cc.cuentacontable_ID REGEXP '^5'
group by n.Dk
But, i have a problem right now... I need REGEX '^5' be a subquery sentence like this
select
sum(IF(l.bandera='DEBITO',l.valor,0)) totdebito,
sum(IF(l.bandera='CREDITO',l.valor,0)) totcredito ,n.nit_ID
from lineaasiento l left join clientesam c on c.Dk=l.clientesmayor_OID
left join proveedores p on p.Dk=l.proveedor_OID left join empleado e on e.Dk=l.empleado_OID
left join banco b on b.Dk=l.banco_OID left join cuentacontable cc on cc.Dk=l.cuentacontable_OID
left join nit n on n.Dk=coalesce(c.nit_OID,p.nit_OID,e.nit_OID,b.nit_OID,null)
where (timefcontable between '2013-01-01' and '2013-12-31') and
estadolinea_OID in (Select Dk from estadoasiento where codigo!=4) and
cc.cuentacontable_ID REGEXP (^a query that returns a lot of values and i need to get the elements that starts by this)
group by n.Dk
It is possible?

For building your regex...
select
'^(' || group_concat(my_value separator '|') || ')' as regex
from
my_table
NOTA: There is a 1024 bytes limit on results returned by group_concat. So if you expect larger results, run the following query before your final query (see below).
set group_concat_max_len=2048
Final query
select
sum(IF(l.bandera='DEBITO',l.valor,0)) totdebito,
sum(IF(l.bandera='CREDITO',l.valor,0)) totcredito ,
n.nit_ID
from
lineaasiento l
left join
clientesam c on c.Dk=l.clientesmayor_OID
left join
proveedores p on p.Dk=l.proveedor_OID
left join
empleado e on e.Dk=l.empleado_OID
left join
banco b on b.Dk=l.banco_OID
left join
cuentacontable cc on cc.Dk=l.cuentacontable_OID
left join
nit n on n.Dk=coalesce(c.nit_OID, p.nit_OID, e.nit_OID, b.nit_OID, null)
inner join
(select '^(' || group_concat(my_value separator '|') || ')' as regex from my_table) values
where
(
timefcontable between '2013-01-01' and '2013-12-31'
)
and estadolinea_OID in (
Select
Dk
from
estadoasiento
where
codigo!=4
)
and cc.cuentacontable_ID REGEXP values.regex
group by
n.Dk

Related

Left join repeats same value of a column in result

I have this sql query :
SELECT t1.id_action, DATE_FORMAT(t1.date_creation,'%d/%m/%Y à %H:%i') AS creation_action,
u.id_utilisateur, p.genre AS genre_utilisateur,
p.nom, av.titre_avancement, b.nom_banque, c.nom_courtier
FROM action AS t1
LEFT JOIN type
ON type.id_type=t1.id_type
LEFT JOIN avancement AS av
ON av.id_avancement=t1.id_avancement
LEFT JOIN utilisateur AS u
ON u.id_utilisateur=t1.id_utilisateur
LEFT JOIN personne AS p
ON p.id_personne=u.id_personne
left join offre_concurrente o
on o.id_dossier = t1.id_dossier
left join banque b
on b.id_banque = o.id_banque
left join courtier_concurrent c
on c.id_courtier_concurrent=o.id_courtier_concurrent
WHERE t1.id_dossier=11 AND t1.fait='1'
GROUP BY t1.id_action
ORDER BY t1.date_creation DESC
And in "b.nom_banque" and "c.nom_courtier" it displays null all the other columns are okay except these 2 i can't figure out the exact problem
You should add all the non-aggregated columns in the select to the group by clause, but I can see you are not using any aggregate function so use DISTINCT instead. Try this:
SELECT DISTINCT t1.id_action, DATE_FORMAT(t1.date_creation,'%d/%m/%Y à %H:%i') AS creation_action,
u.id_utilisateur, p.genre AS genre_utilisateur,
p.nom, av.titre_avancement, b.nom_banque, c.nom_courtier
FROM action AS t1
LEFT JOIN type
ON type.id_type=t1.id_type
LEFT JOIN avancement AS av
ON av.id_avancement=t1.id_avancement
LEFT JOIN utilisateur AS u
ON u.id_utilisateur=t1.id_utilisateur
LEFT JOIN personne AS p
ON p.id_personne=u.id_personne
left join offre_concurrente o
on o.id_dossier = t1.id_dossier
left join banque b
on b.id_banque = o.id_banque
left join courtier_concurrent c
on c.id_courtier_concurrent=o.id_courtier_concurrent
WHERE t1.id_dossier=11 AND t1.fait='1'
ORDER BY t1.date_creation DESC

Ho to get last item in mysql using max()

I want to get the last item as result using max(), but i'm just getting the first item even if im using max()
Here's the SQL code:
SELECT r.correct, r.items, r.percentage,MAX(r.date_taken) as date_taken,
u.username,u.FN, u.user_course_type,
IFNULL(u.user_major_type,'N/A') as user_major_type,u.level_name,
u.section_name
FROM bcc_fs_exam_result r
INNER JOIN
(SELECT u.id_user, u.username, CONCAT(u.lastname,', ',u.firstname) as FN,
c.user_course_type, m.user_major_type, l.level_name, s.section_name
FROM bcc_fs_user u
LEFT JOIN bcc_fs_user_course c on c.id_user_course = u.id_user_course
LEFT JOIN bcc_fs_user_major m on m.id_user_major = u.id_user_major
LEFT JOIN bcc_fs_group_level l ON l.id_level = u.id_level
LEFT JOIN bcc_fs_group_section s ON s.id_section = u.id_section
) u ON r.id_user = u.id_user WHERE r.id_exam = 5 GROUP BY r.id_user
TIA
What I take from your question is that you want to get the "correct", "items", "percentage" ect. columns of the row in bcc_fs_exam_result which has the last or first date.
If that's correct then you can filter bcc_fs_exam_result by first finding what is the min or max date by for each id_user then join that back on the exam results table.
SELECT
r.correct,
r.items,
r.percentage,
r.date_taken,
u.username,
u.FN,
u.user_course_type,
IFNULL(u.user_major_type,'N/A') as user_major_type,
u.level_name,
u.section_name
FROM bcc_fs_exam_result r
INNER JOIN (
SELECT u.id_user,
u.username,
CONCAT(u.lastname,', ',u.firstname) as FN,
c.user_course_type,
m.user_major_type,
l.level_name,
s.section_name
FROM bcc_fs_user u
LEFT JOIN bcc_fs_user_course c on c.id_user_course = u.id_user_course
LEFT JOIN bcc_fs_user_major m on m.id_user_major = u.id_user_major
LEFT JOIN bcc_fs_group_level l ON l.id_level = u.id_level
LEFT JOIN bcc_fs_group_section s ON s.id_section = u.id_section
) u ON r.id_user = u.id_user
INNER JOIN (
SELECT
id_user, max(r.date_taken) as last_date_taken
FROM bcc_fs_exam_result
GROUP BY id_user
) as lastdate ON lastDate.id_user = r.id_user and r.date_taken = lastdate.last_date_taken
which could be more simply written as :
SELECT
r.correct,
r.items,
r.percentage,
r.date_taken,
u.username,
CONCAT(u.lastname,', ',u.firstname) as FN,
c.user_course_type,
IFNULL(m.user_major_type,'N/A') as user_major_type,
l.level_name,
s.section_name
FROM bcc_fs_exam_result r
INNER JOIN (
SELECT
id_user, max(r.date_taken) as last_date_taken
FROM bcc_fs_exam_result
GROUP BY id_user
) as lastdate ON lastDate.id_user = r.id_user and r.date_taken = lastdate.last_date_taken
INNER JOIN bcc_fs_user u on r.id_user = u.id_user
LEFT JOIN bcc_fs_user_course c on c.id_user_course = u.id_user_course
LEFT JOIN bcc_fs_user_major m on m.id_user_major = u.id_user_major
LEFT JOIN bcc_fs_group_level l ON l.id_level = u.id_level
LEFT JOIN bcc_fs_group_section s ON s.id_section = u.id_section
You have assumed that id_user + date_taken is a surrogate key of bcc_fs_exam_result which you should probably enforce with a constraint if at all possible. Otherwise it looks from your sample data that the order of the unique id column id_result follows the date_takenso you might be better to use Max(id_result) rather than Max(date_taken). That would avoid returning duplicate rows for one id_user where two rows of bcc_fs_exam_result have the same taken_date and `id_user.

SQL Query Aggregate Function

This is my query:
select a.id, a.title,count(x.id) as Orders
-- from x_vendordeliveriesareas vda
-- left join x_vendordeliveries vd
-- on vd.id = vda.vendordelivery_id
from x_orders x
left join x_areas a
on x.delivery_area_id = a.id
-- on vda.area_id = a.id
-- left join x_orders x
left join x_vendors v
on v.id = x.vendor_id
where v.title like 'golden dragon%' and (date_format(x.date,'%Y-%m-%d') BETWEEN '2015-01-01' AND '2015-06-30')
and x.status_id=11
and x.country_id =11
and v.city_id=3
group by 1;
This works perfectly fine, but I want to return those areas to which have 0 orders.
I have tried IFNULL and coalesce functions
Your driving table should be x_areas:
select
a.id,
a.title,
coalesce(count(x.id), 0) as Orders
from x_areas a
left join x_orders x
on x.delivery_area_id = a.id
and x.status_id = 11
and x.country_id = 11
and (date_format(x.date,'%Y-%m-%d') BETWEEN '2015-01-01' AND '2015-06-30')
left join x_vendors v
on v.id = x.vendor_id
where
v.title like 'golden dragon%'
and v.city_id = 3
group by 1;
Note that I moved some of your WHERE conditions in the ON clause to prevent the LEFT JOIN from turning into an INNER JOIN, thus giving the same result, with the added x_areas with 0 Orders.

How to use a case statement to determine which table to left join

How to use a case statement to determine which table to left join to this sql sentence:
SELECT c.dentist_id,
c.pack_id,
c.check_id,
sql1.vendor_no ,
p.pack_trans_id,
r.lot_no,
IF(ml.payment_type='Prepay','Pre-Paying','Post-Paying') payment_type,
ml.image_path,
ml.metal_id,
tp.total_paid_refiner,
sql1.percentage,
sql1.contact_percentage,
sql1.agent_percentage,
c.agent_dentist,
c.check_amt,
c.check_image,
c.check_date_sent,
c.check_no,
c.check_clear_date,
ml.spot_gold_price,
ml.total_weight,
ml.estimated_price,
ml.expect_more,
ml.how_long_acquire,
sa.full_name,
pd.company_name,
pd.phone_no,
pd.email
FROM tbl_check AS c
LEFT JOIN tbl_pack_list AS p ON p.pack_id=c.pack_id
LEFT JOIN tbl_pack_list_details AS pd ON pd.pack_id=c.pack_id
LEFT JOIN
(SELECT vendor_no,
paying_contact,
contact_percentage,
percentage,
pay_to,
agent_percentage,
dentist_id did2,
sales_agent_id
FROM tbl_mst_dentist
GROUP BY dentist_id) sql1 ON sql1.did2=c.dentist_id
LEFT JOIN tbl_refining r ON r.pack_id=c.pack_id
LEFT JOIN tbl_metals_list ml ON ml.pack_id=c.pack_id
LEFT JOIN tbl_payment tp ON tp.pack_id=c.pack_id
LEFT JOIN tbl_sales_agent sa ON sa.sales_agent_id=sql1.sales_agent_id
LEFT JOIN
(SELECT * CASE c.agent_dentist WHEN 'a' THEN
(SELECT sa.* ,
sm.state_code
FROM tbl_sales_agent AS sa,
tbl_mst_state AS sm
WHERE sa.sales_agent_id = c.sale_agent_id
AND sa.state=sm.state_name) ELSE
(SELECT *
FROM tbl_mst_dentist
WHERE dentist_id = c.dentist_id))
WHERE 1
AND c.paying_percent !=0
ORDER BY p.pack_trans_id DESC

Joining results of two independent query

I have two working queries:
1st returns the product list:
$sql = "
SELECT a.stockID, a.stockCatID, a.stockName, a.stockCode, a.stockCatCode,
CONCAT_WS(' » ', d.stockCatName, c.stockCatName, b.stockCatName) AS stockPath,
a.stockName AS stockTitle, a.stockID AS uniStock
FROM stockcards a
LEFT OUTER JOIN stockcategories b
ON a.stockCatID = b.stockCatID
LEFT OUTER JOIN stockcategories c
ON b.stockParentCat = c.stockCatID
LEFT OUTER JOIN stockcategories d
ON c.stockParentCat = d.stockCatID ";
2nd is basically returns the difference of total received and total sent whic is remaining quantity:
SELECT DISTINCT (COALESCE(o.totalReceived, 0) + COALESCE(p.totalSent, 0)) as RemainingStock
FROM deliverydetails k
INNER JOIN stockcards l ON k.stockID= l.stockID
LEFT JOIN
(
SELECT m.stockID, SUM(m.dQuantity) totalReceived
FROM deliverydetails m
WHERE m.dQuantity > 0
GROUP BY m.stockID
)
o ON k.stockID = o.stockID
LEFT JOIN
(
SELECT n.stockID, SUM(n.dQuantity) totalSent
FROM deliverydetails n
WHERE n.dQuantity < 0
GROUP BY n.stockID
)
p ON k.stockID = p.stockID
I need to add a new column to first query to display remanining quantity. But couldn't succeed to join this two. Thanks for any tip.
As it seems that your 2nd query just sums positive and negative dQuantities for each stockID, and then adds them together, I think this small change to your 1st query is
all that is needed:
SELECT a.stockID, a.stockCatID, a.stockName, a.stockCode, a.stockCatCode,
CONCAT_WS(' » ', d.stockCatName, c.stockCatName, b.stockCatName) AS stockPath,
a.stockName AS stockTitle, a.stockID AS uniStock,
dd.RemainingStock AS RemainingStock
FROM stockcards a
LEFT OUTER JOIN stockcategories b
ON a.stockCatID = b.stockCatID
LEFT OUTER JOIN stockcategories c
ON b.stockParentCat = c.stockCatID
LEFT OUTER JOIN stockcategories d
ON c.stockParentCat = d.stockCatID
LEFT OUTER JOIN
(SELECT stockID, SUM(dQuantity) AS RemainingStock
FROM deliverydetails
GROUP BY stockID) AS dd
ON dd.stockID = a.stockID