I have a query in MySQL and I am making a crystal report by using this.
Now inside the query i have a column called scan_mode and it is coming from gfi_transaction table. This scan_mode I am using in report to suppress some sections. But some times this value is coming null for some transaction ids.
So now I want to take this scan_mode as separate query so that it will work.
Can any one please help how I can modify the below query to take only scan_mode column.
SELECT
cc.cost_center_code AS cccde,
cc.name AS ccnme,gf.scan_mode,
cc.cost_center_id AS ccid,
site.name AS siteme,
crncy.currency_locale AS currency_locale,
cntry.language AS LANGUAGE,
cntry.country_name AS cntrynm,
crncy.decimal_digits AS rnd,
gf.transaction_no AS Serial_No,
brnd.name AS brand_name,
rsn.description AS reason,
gf.comment AS COMMENT,
ts.status_description AS STATUS,
DATE_FORMAT(gf.created_date,'%d/%m/%Y') AS created_date,
gf.created_by AS created_by,
IFNULL(gf.approval_no,'Not authorized') AS Trans_no,
gf.approved_date AS approval_dt,
gf.approved_by AS approved_by,gf.status AS status1,
IFNULL(loc.cost_center_code,cc.cost_center_code) AS cur_location,
gf.document_ref_no,gf.document_ref_type,
,DATE_FORMAT(document_ref_date1,'%d/%m/%Y')) AS invoice_no
FROM
gfi_transaction gf
INNER JOIN gfi_instruction gfn ON (gf.transaction_id=gfn.transaction_id)
INNER JOIN gfi_document_instruction doc ON (gf.ref_transaction_no = doc.document_instruction_id)
INNER JOIN reason rsn ON (gf.reason_id = rsn.reason_id)
INNER JOIN gfi_status ts ON (gf.status = ts.gfi_status_id)
INNER JOIN transaction_type tt ON (gf.transaction_type_id = tt.transaction_type_id)
INNER JOIN brand brnd ON(gf.brand_id=brnd.brand_id)
-- cc details
INNER JOIN cost_center cc ON (brnd.parent_brand = cc.brand_id OR gf.brand_id = cc.brand_id)
INNER JOIN site site ON(cc.site_id = site.site_id)
INNER JOIN country cntry ON (site.country_id = cntry.country_id)
INNER JOIN currency crncy ON (cntry.currency_id=crncy.currency_id)
LEFT OUTER JOIN alshaya_location_details loc ON
(gf.brand_id = loc.brand_id AND loc.cost_center_id = gf.cost_centre_id)
LEFT OUTER JOIN alshaya_location_details locto ON
(locto.cost_center_id = gf.from_cost_center_id)
WHERE
gf.transaction_id='{?TransID}'
AND rsn.transaction_type_id IN (10,11,14)
wow, that's a big query. I ran across a similar problem in a query i was building and found the if syntax to be a solution to my problem. This was also answered in this question: MYSQL SELECT WITHIN IF Statement
$psdb->query = "SELECT count, s.classid,
if (k.sic != k.siccode, k.siccode, s.siccode) as siccode,
if (k.sic != k.siccode, k.sicdesc, s.sicdesc) as sicdesc,
if (k.sic != k.siccode, k.sicslug, s.sicslug) as sicslug
FROM ...
It looks like scan_mode column comes from "gfi_transaction" table which seems to be primary table in your query. If you get null for this column then it means your table itself have NULL value for this column. Taking that separately in a query wont solve your problem. Try replacing null with a default value and handle it in code. You can add default value instead of NULL by using ifnull(scan_mode, 'default')
Related
I have the following query generated with the Typeorm querybuilder
Current behavior:
Right now what is happening is that marines are correctly filtered but selected joins are also filtered by the given condition. returning only the dock that matches the condition instead of all the docks that belong to the marine.
Desired result:
I want to obtain all marines that have at least one dock whose name is 'dock 1'. And I want to include all docks belonging to that marine without taking their name into account.
How should i execute this query?
Any help would be much appreciated.
mariadb Ver 15.1
typeorm#0.2.37
SELECT `c`.`id` AS `c_id`,
`c`.`name` AS `c_name`,
`c`.`description` AS `c_description`,
`c`.`FkId` AS `c_FkId`,
`c`.`FkModel` AS `c_FkModel`,
`c`.`isActive` AS `c_isActive`,
`c`.`createdAt` AS `c_createdAt`,
`c`.`updatedAt` AS `c_updatedAt`,
`c`.`phones` AS `c_phones`,
`c`.`emails` AS `c_emails`,
`c`.`mainImage` AS `c_mainImage`,
`c`.`galleryImages` AS `c_galleryImages`,
`c`.`addressDetailsId` AS `c_addressDetailsId`,
`c_Docks`.`id` AS `c_Docks_id`,
`c_Docks`.`name` AS `c_Docks_name`,
`c_Docks`.`description` AS `c_Docks_description`,
`c_Docks`.`FkId` AS `c_Docks_FkId`,
`c_Docks`.`FkModel` AS `c_Docks_FkModel`,
`c_Docks`.`isActive` AS `c_Docks_isActive`,
`c_Docks`.`createdAt` AS `c_Docks_createdAt`,
`c_Docks`.`updatedAt` AS `c_Docks_updatedAt`,
`c_Docks`.`MarineId` AS `c_Docks_MarineId`
FROM `marine` `c`
LEFT JOIN `dock` `c_Docks` ON `c_Docks`.`MarineId` = `c`.`id`
WHERE `c`.`isActive` = true
AND (`c_Docks`.`name` = 'dock 1')
# ORDER BY c_id DESC
Step 1: Filter out all the rows relevant from table marine:
select from marine C where c.isActive = true
Step 2: Make the earlier SQL an inline view and left join it with table dock and apply the filter on dock table.
So, the SQL should look like this:
SELECT c.<column_names> ,
c_docks.<column_names>
FROM (
SELECT <column_names>
FROM marine
WHERE isActive = true) c
LEFT OUTER JOIN dock c_docks
ON c.id = c_docks.marine_id
AND c_docks.NAME = 'dock 1';
You can join with dock twice. Once to filter on the dock name, and another time to get all docks.
SELECT `c`.`id` AS `c_id`,
`c`.`name` AS `c_name`,
`c`.`description` AS `c_description`,
`c`.`FkId` AS `c_FkId`,
`c`.`FkModel` AS `c_FkModel`,
`c`.`isActive` AS `c_isActive`,
`c`.`createdAt` AS `c_createdAt`,
`c`.`updatedAt` AS `c_updatedAt`,
`c`.`phones` AS `c_phones`,
`c`.`emails` AS `c_emails`,
`c`.`mainImage` AS `c_mainImage`,
`c`.`galleryImages` AS `c_galleryImages`,
`c`.`addressDetailsId` AS `c_addressDetailsId`,
`c_Docks`.`id` AS `c_Docks_id`,
`c_Docks`.`name` AS `c_Docks_name`,
`c_Docks`.`description` AS `c_Docks_description`,
`c_Docks`.`FkId` AS `c_Docks_FkId`,
`c_Docks`.`FkModel` AS `c_Docks_FkModel`,
`c_Docks`.`isActive` AS `c_Docks_isActive`,
`c_Docks`.`createdAt` AS `c_Docks_createdAt`,
`c_Docks`.`updatedAt` AS `c_Docks_updatedAt`,
`c_Docks`.`MarineId` AS `c_Docks_MarineId`
FROM `marine` `c`
JOIN `dock` `c_Docks` ON `c_Docks`.`MarineId` = `c`.`id`
JOIN `dock` `dock_1` ON `dock_1`.`MarineId` = `c`.`id`
WHERE `c`.`isActive` = true
AND `dock_1`.`name` = 'dock 1'
There's no reason to use LEFT JOIN here, since you don't want to include marines with no matching dock.
My mysql query is too slow and i don't know how to optimize it. My webapp cant load this query because take too much time to run and the webserver have a limit time to get the result.
SELECT rc.trial_id,
rc.created,
rc.date_registration,
rc.agemin_value,
rc.agemin_unit,
rc.agemax_value,
rc.agemax_unit,
rc.exclusion_criteria,
rc.study_design,
rc.expanded_access_program,
rc.number_of_arms,
rc.enrollment_start_actual,
rc.target_sample_size,
(select name from repository_institution where id = rc.primary_sponsor_id) as
primary_sponsor,
(select label from vocabulary_studytype where id = rc.study_type_id) as study_type,
(select label from vocabulary_interventionassigment where id =
rc.intervention_assignment_id) as intervention_assignment,
(select label from vocabulary_studypurpose where id = rc.purpose_id) as study_purpose,
(select label from vocabulary_studymasking where id = rc.masking_id) as study_mask,
(select label from vocabulary_studyallocation where id = rc.allocation_id) as
study_allocation,
(select label from vocabulary_studyphase where id = rc.phase_id) as phase,
(select label from vocabulary_recruitmentstatus where id = rc.recruitment_status_id) as
recruitment_status,
GROUP_CONCAT(vi.label)
FROM
repository_clinicaltrial rc
inner JOIN repository_clinicaltrial_i_code rcic ON rcic.clinicaltrial_id = rc.id JOIN
vocabulary_interventioncode vi ON vi.id = rcic.interventioncode_id
GROUP BY rc.id;
Using inner join instead join could be a solution?
Changing to JOINs vs continuous selects per every row will definitely improve. Also, since you are using MySQL, using the keyword "STRAIGHT_JOIN" tells MySQL to do the query in the order I provided. Since your "rc" table is the primary and all the others are lookups, this will make MySQL use it in that context rather than hoping some other lookup table be the basis of the rest of the joins.
SELECT STRAIGHT_JOIN
rc.trial_id,
rc.created,
rc.date_registration,
rc.agemin_value,
rc.agemin_unit,
rc.agemax_value,
rc.agemax_unit,
rc.exclusion_criteria,
rc.study_design,
rc.expanded_access_program,
rc.number_of_arms,
rc.enrollment_start_actual,
rc.target_sample_size,
ri.name primary_sponsor,
st.label study_type,
via.label intervention_assignment,
vsp.label study_purpose,
vsm.label study_mask,
vsa.label study_allocation,
vsph.label phase,
vrs.label recruitment_status,
GROUP_CONCAT(vi.label)
FROM
repository_clinicaltrial rc
JOIN repository_clinicaltrial_i_code rcic
ON rc.id = rcic.clinicaltrial_id
JOIN vocabulary_interventioncode vi
ON rcic.interventioncode_id = vi.id
JOIN repository_institution ri
on rc.primary_sponsor_id = ri.id
JOIN vocabulary_studytype st
on rc.study_type_id = st.id
JOIN vocabulary_interventionassigment via
on rc.intervention_assignment_id = via.id
JOIN vocabulary_studypurpose vsp
ON rc.purpose_id = vsp.id
JOIN vocabulary_studymasking vsm
ON rc.masking_id = vsm.id
JOIN vocabulary_studyallocation vsa
ON rc.allocation_id = vsa.id
JOIN vocabulary_studyphase vsph
ON rc.phase_id = vsph.id
JOIN vocabulary_recruitmentstatus vrs
ON rc.recruitment_status_id = vrs.id
GROUP BY
rc.id;
One final note. You are using a GROUP BY and applying to the GROUP_CONCAT() which is ok. However, proper group by says you need to group by all non-aggregate columns, which in this case is every other column in the list. You may know this, and the fact the lookups will be the same based on the "rc" associated columns, but its not good practice to do so.
Your joins and subqueries are probably not the problem. Assuming you have correct indexes on the tables, then these are fast. "Correct indexes" means that the id column is the primary key -- a very reasonable assumption.
My guess is that the GROUP BY is the performance issue. So, I would suggest structuring the query with no `GROUP BY:
select . . .
(select group_concat(vi.label)
from repository_clinicaltrial_i_code rcic
vocabulary_interventioncode vi
on vi.id = rcic.interventioncode_id
where rcic.clinicaltrial_id = rc.id
)
from repository_clinicaltrial rc ;
For this, you want indexes on:
repository_clinicaltrial_i_code(clinicaltrial_id, interventioncode_id)
vocabulary_interventioncode(id, label)
Good day,
I have a small issue with MySQL Distinct.
Trying the following query in my system :
SELECT DISTINCT `booking_id`, `booking_ticket`, `booking_price`, `bookingcomment_id`, `bookingcomment_message` FROM `mysystem_booking`
LEFT JOIN `mysystem_bookingcomment` ON `mysystem_booking`.`booking_id` = `mysystem_bookingcomment`.`bookingcomment_link`
WHERE `booking_id` = 29791
The point is that there are bookings like 29791 that have many comments added.
Let's say 10. Then when running the above query I see 10 results instead of one.
And that's not the way DISTINCT supposes to work.
I simply want to know if there are any comments. If the comment ID is not 0 then there is a comment. Of course I can add COUNT(blabla) as comment_number but that's a whole different story. For me now I'd like just to have this syntax right.
You may try aggregating here, to find which bookings have at least a single comment associated with them:
SELECT
b.booking_id,
b.booking_ticket,
b.booking_price
FROM mysystem_booking b
LEFT JOIN mysystem_bookingcomment bc
ON b.booking_id = bc.bookingcomment_link
WHERE
b.booking_id = 29791
GROUP BY
b.booking_id
HAVING
COUNT(bc.bookingcomment_link) > 0;
Note that depending on your MySQL server mode, you might have to also add the booking_ticket and booking_price columns to the GROUP BY clause to get the above query to run.
You can try below - using a case when expression
SELECT DISTINCT `booking_id`, `booking_ticket`, `booking_price`, `bookingcomment_id`,
case when `bookingcomment_message`<>'0' then 'No' else 'Yes' end as comments
FROM `mysystem_booking`
LEFT JOIN `mysystem_bookingcomment` ON `mysystem_booking`.`booking_id` = `mysystem_bookingcomment`.`bookingcomment_link`
WHERE `booking_id` = 29791
I don't know if the title is correct but here goes my problem.
So, I want to create View in phpmyadmin using data from several tables (picture below), View that represents maintenance for lamps with fields from several tables (substation, post_type, area, lamp_type, failure and maintenance)
Here are tables with connections:
I've manage somehow and created something like this(picture below), which I managed to create using this block of code:
CREATE OR REPLACE VIEW
v_lamp_I
AS
SELECT
lamps.id,
substation.code AS sub_code,
substation.name AS sub_name,
lamps.lamp_code,
post_type.descript AS post_ty,
lamp_type.descript AS lamp_ty,
area.descript AS area_name,
rasvjeta.adress,
DATE_FORMAT(date_maintenance, "%d.%m.%Y.") AS date_main,
lamps.geo_long,
lamps.geo_lat
FROM lamps
INNER JOIN substiation ON substiation.id = lamps.substiation_id
INNER JOIN post_type ON post_type.id = lamps.post_type_id
INNER JOIN lamp_type ON lamp_type.id = lamps.lamp_type_id
INNER JOIN area ON area.id = rasvjeta.area_id
INNER JOIN maintenance ON maintenance.lamps_id = lamps.id
I've managed to create view but the problem is with that view I can see only rows/lamps(sifra_lampe) which were maintained, only 4. In table lamps
I've 24 entries in and only 4 entries for maintenance.But, I want to see all 24 entries and if there was no maintenance for that particular lamp, field can be empty with date format (00-00-00 or it can be NULL) and for entries/lamps that were maintained I want to be visible date field.
Here is table lamps with entries.
And here is view with maintenance date. As you can see there are only 6 entries
I want to see the rest of the entries, for lamps that were not maintained entries can be null or date format like this (00-00-00) and for lamps that were maintained date format can stay the same, in short I want to see all entries not only those which were maintained. Thank you and sorry for long question. I didn't know how to construct meaningful and short question so wrote everything.
create or replace view
v_lamp_I as
SELECT lamps.id,
substation.code AS sub_code,
substation.name AS sub_name,
lamps.lamp_code,
post_type.descript AS post_ty,
lamp_type.descript AS lamp_ty,
area.descript AS area_name,
rasvjeta.adress,
lamps.geo_long,
lamps.geo_lat
FROM lamps
INNER JOIN substiation ON substiation.id = lamps.substiation_id
INNER JOIN post_type ON post_type.id = lamps.post_type_id
INNER JOIN lamp_type ON lamp_type.id = lamps.lamp_type_id
INNER JOIN area ON area.id = rasvjeta.area_id;
CREATE OR REPLACE VIEW
v_lamp_new
AS
select v_lamp_I.*,DATE_FORMAT(date_maintenance, "%d.%m.%Y.") AS date_main
from v_lamp_I
LEFT JOIN maintenance ON v_lamp_I.id = maintenance.lamps_id;
CREATE OR REPLACE VIEW
v_lamp_I
AS
select tbl_lamp.*,DATE_FORMAT(date_maintenance, "%d.%m.%Y.") AS date_main
from (SELECT lamps.id,
substation.code AS sub_code,
substation.name AS sub_name,
lamps.lamp_code,
post_type.descript AS post_ty,
lamp_type.descript AS lamp_ty,
area.descript AS area_name,
rasvjeta.adress,
lamps.geo_long,
lamps.geo_lat
FROM lamps
INNER JOIN substiation ON substiation.id = lamps.substiation_id
INNER JOIN post_type ON post_type.id = lamps.post_type_id
INNER JOIN lamp_type ON lamp_type.id = lamps.lamp_type_id
INNER JOIN area ON area.id = rasvjeta.area_id) as tbl_lamp
LEFT JOIN maintenance ON tbl_lamp.id = maintenance.lamps_id
I am trying to build a rather complex view in MySQL and want to do a conditional, but it sems always to fail.
My view (simplified) is
Select entry AS Entry, ,(select count(`poitems`.`entry`) AS `count(poitems.entry)` from `poitems` where (`poitems`.`PurchaseOrder` = `purchaseorder`.`entry`)) AS `TotalEntries`, from purchase orders
this is OK but what I am trying to do is add something like
if ((select count(`poitems`.`entry`) = 0),'query.png',NULL) AS Queryflag
or just test the value of TotalEntries.
Help appreciated! Thanks!
I'm not 100% sure on the names of the columns in purchaseorder or poitems tables but the following should get you headed in the right direction:
select t.Entry,
case when t.TotalEntries > 0 then 'query.png' else null end as Queryflag
from
(
select po.entry as Entry,
count(*) as TotalEntries
from purchaseorder po
left outer join poitems poi on poi.purchaseorder = po.entry
group by po.entry
) t;