Although the query returns the result but the group by Month returns result alphabetically like April,August,June ... but it should return result Chronologically like Jan ,Feb,....
SELECT Concat(Monthname(a.fdate), '-', Year(a.fdate)) AS Month,
s.new_state AS State,
d.new_dist AS District,
b.ifbook AS Book,
Sum(a.amt) AS Amount
FROM str a
JOIN sc b
ON b.scd = a.isc
JOIN USER c
ON a.ed = c.str
JOIN state_mapping s
ON b.state = s.org_state
JOIN dist_mapping d
ON b.dist = d.org_dist
WHERE Trim(b.ifbook) <> ''
AND b.ifbook IS NOT NULL
AND b.ifbook NOT LIKE '%TR%'
AND Trim(d.new_dist) <> ''
AND d.new_dist IS NOT NULL
GROUP BY b.ifbank,
d.new_dist,
s.new_state,
month
How can I modify the query to achieve the same?
Without knowing anything about your model I could suggest you to give this a shot:
select
concat(monthname(a.fdate),'-',year(a.fdate)) Month,
s.new_state State,
d.new_dist District,
b.ifbook Book,
sum(a.amt) Amount
from str a
JOIN sc b on b.scd = a.isc
JOIN user c on a.ed = c.str
JOIN state_mapping s on b.state = s.org_state
JOIN dist_mapping d on b.dist = d.org_dist
where TRIM(b.ifbook) <> '' and b.ifbook IS NOT NULL and b.ifbook not like '%TR%'
and TRIM(d.new_dist) <> '' and d.new_dist IS NOT NULL
group by b.ifbank, d.new_dist, s.new_state, Month
order by year(a.fdate), month(a.fdate)
Related
I am using the following code to get a grouped list of voyage types and their respective voyages.
public function getVoyageTypesWithTrips() {
//query
$this->db->query('
SELECT voyagetype_name
, voyagetype_description
, voyagetype_image
, voyage_id
, voyage_name
, voyage_startDate
FROM voyagetypes
LEFT
JOIN voyages
ON voyagetypes.voyagetype_id = voyages.voyage_type
WHERE voyagetype_deleted != 1
');
//get the results
$results = $this->db->resultSetGrouped();
return $results;
}
//get results set as array of objects - grouped
public function resultSetGrouped() {
$this->execute();
return $this->statement->fetchAll(PDO::FETCH_GROUP);
}
What I want to do is limit the voyages table to only show the 3 most closest records to today instead of returning all the voyages for that type.
So returning
Category 1 (Voyage next week, voyage week after, voyage week after that, no more but loads in table)
Category 2 (voyage tomorrow, no more in this category)
Category 3 (no voyages)
I initially tried ORDER BY and LIMIT but this doesn't work with the PDO::FETCH_GROUP I think.
I believe I need to have my SQL order & limit the joined table prior to sending to the fetch_group??? So something like
$this->db->query('
SELECT voyagetype_name
, voyagetype_description
, voyagetype_image
, voyage_id
, voyage_name
, voyage_startDate
FROM voyagetypes
LEFT
JOIN voyages
ON voyagetypes.voyagetype_id = voyages.voyage_type
APPLY THE SORT AND LIMIT TO THE JOINED TABLE
WHERE voyagetype_deleted != 1
');
One option is to filter with a subquery:
select vt.voyagetype_name, vt.voyagetype_description, vt.voyagetype_image, v.voyage_id, v.voyage_name, v.voyage_startdate
from voyagetypes vt
left join voyages v
on v.voyagetype_id = vt.voyage_type
and (
select count(*)
from voyages v1
where
v1.voyage_type = vt.voyage_type
and v1.voyage_startdate > v.voyage_startdate
) < 3
where vt.voyagetype_deleted <> 1
Or, if you are running MYSQL 8.0, you can just use rank():
select *
from (
select
vt.voyagetype_name,
vt.voyagetype_description,
vt.voyagetype_image,
v.voyage_id,
v.voyage_name,
v.voyage_startdate,
rank() over(partition by vt.voyage_type order by v.voyage_startdate desc) rn
from voyagetypes vt
left join voyages v on v.voyagetype_id = vt.voyage_type
where vt.voyagetype_deleted <> 1
) t
where rn <= 3
I have a similar question to How to use GROUP BY to concatenate strings in MySQL? , however for this example for mytable table
id string aggr
1 A NULL
1 B NULL
2 F NULL
The difference is I need to update the table to get this results:
id string aggr
1 A A|B|
1 B A|B|
5 C C|E|C|
5 E C|E|C|
5 C C|E|C|
2 F F|
As result the same id we have the same newcolumn values.
It is absolutely fine to add a delimiter |at the very end of the string. That way I can even faster count how many "items" are in the newcolumn without adding +1 because of the absense at the very end (just in between). Also I won't care about validation (if I have a pipe right before) when appending another part or two into aggr column.
Thank you.
You can try this query :
UPDATE my_table t
SET aggr = (
SELECT * FROM (
SELECT CONCAT(GROUP_CONCAT(t2.string SEPARATOR '|'), '|')
FROM my_table t2
WHERE t2.id = t.id
) AS X
)
You could a group_concat joined on original table
select a.id, a.string , b.aggr
from my_table a
inner join (
select id, group_concat(string SEPARATOR '|') as aggr
from my_table
group by id
) b on a.id = b.id
I've been trying to find a solution to my problem for a couple of hours now and can't come up with the right query. I have two tables, stocktake_scans and stocktake_items. I need to select data from both tables and group them together. The query that I have at the moment is this:
SELECT
a.department_description, a.sub_department_description, a.total_cost, a.total_retail, SUM(a.qty) AS qty, a.total_vat, a.vat_rate
FROM (
SELECT (CASE WHEN TRIM(IFNULL(sp.department_description, '')) = '' THEN 'N/A' ELSE sp.department_description END) AS department_description,
(CASE WHEN TRIM(IFNULL(sp.sub_department_description, '')) = '' THEN 'N/A' ELSE sp.sub_department_description END) AS sub_department_description,
SUM(sp.unit_cost_price * ss.quantity) AS total_cost,
SUM(sp.unit_retail_price * ss.quantity) AS total_retail,
sum(ss.quantity) AS qty,
(SUM(sp.unit_cost_price*ss.quantity)) * (sv.vat_rate/100) AS total_vat,
sv.vat_rate as vat_rate
FROM
stocktake_scans ss
INNER JOIN stocktake_products sp ON ss.stocktake_product_id = sp.stocktake_product_id
LEFT JOIN stocktake_vat_codes sv ON sv.vat_code = sp.vat_code AND sv.stocktake_id = '5778'
WHERE ss.stocktake_id = '5778'
GROUP BY sp.department_description, sp.sub_department_description
UNION ALL
SELECT (CASE WHEN TRIM(IFNULL(si.department_description, '')) = '' THEN 'N/A' ELSE si.department_description END) AS department_description,
'N/A' as sub_department_description,
SUM(si.unit_cost_price * si.quantity) AS total_cost,
SUM(si.unit_retail_price * si.quantity) AS total_retail,
sum(si.quantity) AS qty,
SUM(si.unit_cost_price * quantity)*(sv.vat_rate/100) AS total_vat,
sv.vat_rate as vat_rate
FROM stocktake_items si
LEFT JOIN stocktake_vat_codes sv ON sv.vat_code = si.vat_code AND sv.stocktake_id = '5778'
WHERE si.stocktake_id = '5778' GROUP BY si.department_description ) a
GROUP
BY a.department_description, a.sub_department_description
This doesn't fully do the job. I get all the data from stocktake_scans, followed by data from stocktake_items.
I get the below as the first result
And then at the end of the excel file I also get this
What is the right way of doing this, so that both Alcohol figures are displayed in one place?
Add ORDER BY a.department_description, a.sub_department_description before the last GROUP BY
SELECT `user_appoint`.`ApptDateTime` AS ApptDate,`user_appoint`.`id` AS appt_id, `user_appoint`.`ref_no` AS ref_no, `user_appoint`.`status_id` AS status_id, `user_det`.`pass_no`, `user_det`.`f_name` AS fname, `user_appoint`.`date`, `user_det`.`l_name` AS lname, `user_det`.`dob` AS dob, `tbl_pi`.`Pi`, `tbl_vesselmaster`.`id` AS Vid, `user_det`.`id` AS user_id, `user_appoint`.`dr_comments` AS Remarks
FROM (`user_det`)
JOIN `user_appoint` ON `user_appoint`.`u_id` = `user_det`.`id`
LEFT JOIN `tbl_pi` ON `user_appoint`.`id` = `tbl_pi`.`ApptId`
JOIN `tbl_rank` ON `user_appoint`.`rank` = `tbl_rank`.`rank_id`
JOIN `tbl_typeofmedical` ON `tbl_typeofmedical`.`Id`=`user_appoint`.`purpose`
JOIN `tbl_vesselmaster` ON `tbl_vesselmaster`.`id` = `user_appoint`.`vessel`
JOIN `tbl_clinic_list` ON `tbl_clinic_list`.`Id` = `user_appoint`.`ClinicId`
JOIN `pate_status` ON `pate_status`.`id`=`user_appoint`.`status_id`
LEFT JOIN `tbl_doctorlist` ON `tbl_doctorlist`.`id`=`user_appoint`.`DrId`
LEFT JOIN `tbl_fleetvessel` ON `tbl_fleetvessel`.`VesselId` = `user_appoint`.`vessel`
WHERE `user_appoint`.`void` = 0
AND `user_appoint`.`comp_id` = '123'
AND `user_det`.`3cc_id` LIKE '%%'
AND `user_appoint`.`ref_no` LIKE '%%'
AND `user_appoint`.`DrId` LIKE '%%'
AND `tbl_fleetvessel`.`FleetId` LIKE '%%'
AND `ApptDateTime` LIKE '%%'
ORDER BY `user_appoint`.`ApptDateTime` DESC
LIMIT 15
This is myquery which return following result
ApptDate f_name l_name
-------------- ------- -------
13-11-2015 xyz pqr
06-11-2015 abc uio
04-11-2015 qwe jkl
I want the table to show today's result on top followed by future results and then the rest of results.
Just change the order by clause of your query:
ORDER BY DATE_FORMAT(`user_appoint`.`ApptDateTime`, '%d-%m-%Y') = DATE_FORMAT(NOW(), '%d-%m-%Y') DESC, `user_appoint`.`ApptDateTime` > NOW() DESC, `user_appoint`.`ApptDateTime` DESC
That way the first result is the one where the date matches today, the next results are those where the date is greater than today (=in the future) and then the rest in descending order.
Simply use CASE WHEN with your conditions in your ORDER BY:
ORDER BY
CASE
WHEN DATE(user_appoint.ApptDateTime) = CURDATE() THEN 1
WHEN DATE(user_appoint.ApptDateTime) > CURDATE() THEN 2
ELSE 3
END
Im trying to combine tables with LEFT JOIN and SUBSTR LOCATE. One of the tables (ClientService) has a column named description and the record i need is between " "
for example: This is a test "Example". I need Example to compare with my other table (HostingAccount)
This is the query i have.
SELECT
CS.ClientServiceID,
S.ServiceID,
CS.InvoicePeriod,
CS.Period,
S.Price,
S.ServiceCategoryID,
IF(LENGTH(CS.Description) > 0, CS.Description, S.Description) AS Description,
CS.Discount,
DATE_FORMAT(CS.StartDate, "%d-%m-%Y") AS StartDate,
'.($Timestamp === TRUE ? 'UNIX_TIMESTAMP(CS.PayedUntill)' : 'DATE_FORMAT(IFNULL(CS.PayedUntill, DATE_ADD(CS.StartDate, INTERVAL 1 YEAR)), "%d-%m-%Y")').' AS PayedUntill,
DATEDIFF(NOW(), CS.PayedUntill) AS PayedUntillDifference,
CS.ReferenceID,
CS.External,
CS.Redirect,
CS.RedirectType,
CS.Active,
H.HostingID,
H.ServerIP,
H.Username
FROM ClientService AS CS
JOIN Client AS C
ON C.ClientID = CS.ClientID
JOIN Service AS S
ON S.ServiceID = CS.ServiceID
LEFT JOIN Hosting AS H
ON H.HostingID = CS.ReferenceID
AND H.ClientID = C.ClientID
---> LEFT JOIN HostingAccount AS HA
ON HA. <----
WHERE CS.ClientServiceID = :CSID
AND C.ClientID = :CID
AND CS.Active IN (1,5,6,9)
I've marked the LEFT JOIN HostingAccount with ---> <--- and it has the Example description in it without the " "
This query i've tested and it gives me the record without the " " from table ClientService
SELECT SUBSTR(Description, LOCATE('"',Description)+1,
(CHAR_LENGTH(Description) - LOCATE('"',REVERSE(Description)) -
LOCATE('"',Description))) from ClientService
Question:
How can i combine the SUBSTR query with the LEFT JOIN HostingAccount AS HA
ON HA.description (Without the delimiter) = CS.description (Between the delimiter)
I have not tested the following and I'm not 100% sure I followed the question but I think you mean something like this?
<?php
$sql='SELECT
CS.`ClientServiceID`,
S.`ServiceID`,
CS.`InvoicePeriod`,
CS.`Period`,
S.`Price`,
S.`ServiceCategoryID`,
IF( LENGTH( CS.`Description` ) > 0, CS.`Description`, S.`Description`) AS "Description",
CS.`Discount`,
DATE_FORMAT(CS.`StartDate`, "%d-%m-%Y") AS "StartDate",
' .( $Timestamp === TRUE ? 'UNIX_TIMESTAMP( CS.`PayedUntill` )' : 'DATE_FORMAT(IFNULL(CS.`PayedUntill`, DATE_ADD(CS.`StartDate`, INTERVAL 1 YEAR)), "%d-%m-%Y")' ) . ' AS "PayedUntill",
DATEDIFF(NOW(), CS.`PayedUntill`) AS "PayedUntillDifference",
CS.`ReferenceID`,
CS.`External`,
CS.`Redirect`,
CS.`RedirectType`,
CS.`Active`,
H.`HostingID`,
H.`ServerIP`,
H.`Username`
FROM `ClientService` CS
JOIN `Client` C ON C.ClientID = CS.ClientID
JOIN `Service` S ON S.ServiceID = CS.ServiceID
LEFT JOIN `Hosting` H ON H.HostingID = CS.ReferenceID AND H.ClientID = C.ClientID
LEFT JOIN `HostingAccount` HA ON HA.`description`=(
SELECT SUBSTR(`Description`, LOCATE( \'"\', `Description` )+1,
( CHAR_LENGTH( `Description`) - LOCATE(\'"\',REVERSE(`Description`) ) -
LOCATE(\'"\',Description)))
from `ClientService`
)
WHERE CS.`ClientServiceID` = :CSID
AND C.`ClientID` = :CID
AND CS.`Active` IN (1,5,6,9)';
?>