query not returning expected result? - mysql

I have 2 tables:
1)report_details
2) reports
Query :
SELECT COUNT(channel),DATE_FORMAT(date,'%d/%m/%Y') AS niceDate,
channel FROM `report_details`
JOIN report on report.report_id=report_details.report_id
where report.report_hash='abcd'
GROUP BY channel,niceDate;
output
expected output

$value = DB::table('report_details')
->join('reports','report_details.report_id','=','reports.report_id')
->groupBy('channel')->get();
// print_r($value);
also use DB; in your controller

Problem :
as far as i can see there is a problem in your query, it seems you will need more than a simple group by since you want an aggregation. So you probably want to use GROUP_CONCAT() to to get your chanels, but you will need an inner select if you want to group all chanels of the same date on 1 line but with separator
Modified query :
SELECT GROUP_CONCAT(cnt),niceDate,GROUP_CONCAT(channel)channel FROM
(
SELECT COUNT(channel) as cnt ,DATE_FORMAT(date,'%d/%m/%Y')
AS niceDate,group_concat(channel) channel
FROM `report_details` JOIN report on report.report_id=report_details.report_id
where report.report_hash='abcd' GROUP BY chanel,niceDate
) f
GROUP BY niceDate ;
Explication
I put the first query as an inner select so that you could have all chanels of the same date on 1 line, you can't do it in 1 select since Group_Concat can't have a count inside unless it comes from an inner select like in this example
I added the use of group_concat(chanel) so that you get the list of chanel and not separate line for each of them
if you want more information on group_concat here is the link to the doc :
Documentation

Use the GROUP_CONCAT() function:
SELECT GROUP_CONCAT(COUNT),GROUP_CONCAT(channel)channel,niceDate FROM
(
SELECT COUNT(channel)COUNT, DATE_FORMAT(date, '%d/%m/%Y') AS niceDate,channel
FROM `report_details`
JOIN report ON report.report_id = report_details.report_id
WHERE report.report_hash = 'abcd'
GROUP BY niceDate,channel
)Z
GROUP BY niceDate ;

Related

Not able to use GROUP BY with join query in MySQL

I need to execute the below Query but not able to do it.
SELECT *
FROM (SELECT *
FROM rider_status
order by created_date DESC) as riderActice
INNER JOIN rider_user ON rider_userId = rider_user.id
Where rider_user.isActive = 1
AND online_status = 1
GROUP by rider_userId
Error: "#1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'riderActice.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by"
I have read some blogs and found the below solution.
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'ONLY_FULL_GROUP_BY',''));
But Yet executing above solution I am getting another issue which is
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'ONLY_FULL_GROUP_BY',''));
Please let me know if I am missing something or doing it wrong
You can not select all(* means all) columns from a table and do a group by one column. That is why you are getting an error. If the column is in the select clause and it is not a part of aggregate function then it has to be in a group by clause.
Also, use the aliases you have created riderActice when joining two tables(subquery and a table).
Here is a small demo demonstrating first part of my answer.
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=b10244e667e59bffb146170014dc69ba
If you want to select all columns then do it like this:
SELECT riderActice.rider_userId
, riderActice.created_date
, rider_user.id
, rider_user.isActive
, rider_user.online_status
FROM rider_status as riderActice
INNER JOIN rider_user ON riderActice.rider_userId = rider_user.id
WHERE rider_user.isActive = 1
AND rider_user.online_status = 1
GROUP BY riderActice.rider_userId
, riderActice.created_date
, rider_user.id
, rider_user.isActive
, rider_user.online_status
If you do not want to group by every column then explain to us what is it that you need, but this is the answer to your question.

Not getting count of different string - MySql

I have one query as given below,
select device_id,CAST(device_dtt_st as date),count(*) as g,'' as s,'' as m
from event_data_170309
where device_id ='8D-15-DB'and raw_data like %GPRS%'
group by CAST(device_dtt_st as date)
union
select device_id,CAST(device_dtt_st as date),'' as g,count(*) as s,'' as m
from event_data_170309
where device_id ='8D-15-DB' and raw_data like '%SMS%'
group by CAST(device_dtt_st as date)
union
select device_id,CAST(device_dtt_st as date),'' as g,'' as s,count(*) as m
from event_data_170309
where device_id ='8D-15-DB'and !(raw_data like '%SMS%' or raw_data like '%GPRS%')
group by CAST(device_dtt_st as date);
and I got output as in two different row, but I want count in only one row.
see the below scenario,
Union will return multiple rows only.
You will need to wrap all these queries with another query and then count it.
ex.
select count(param), sum(param), param
from
(
select param as param, count(param)
union
another query with same column output
union
yet another query with same column output
) as childQuery
group by childQuery.param
EDIT
Added a aggregated function, whichever you want to use.
EDIT2
SELECT
DEVICE_ID,
DATE,
SUM(IF(DATA LIKE %SMS%,1,0)) AS TOTAL_SMS,
SUM(IF(DATA LIKE %GPRS%,1,0)) AS TOTAL_GPRS,
SUM(IF(DATA NOT LIKE %GPRS% AND DATA NOT LIKE %SMS%,1,0)) AS TOTAL_OTHER,
FROM
YOUR_TABLE T
GROUP BY
T.DATE
ABove query will work for your desired output

The query gives single row query returns more than one row

I'm trying to show staff_code, staff_name and dept_name for those who have taken one book.
Here's my query:
SELECT SM.STAFF_CODE,SM.STAFF_NAME,DM.DEPT_NAME,BT.BOOK_CODE
FROM STAFF_MASTER SM,DEPARTMENT_MASTER DM,BOOK_TRANSACTIONS BT
WHERE SM.DEPT_CODE =DM.DEPT_CODE
AND SM.STAFF_CODE = (
SELECT STAFF_CODE
FROM BOOK_TRANSACTIONS
HAVING COUNT(*) > 1
GROUP BY STAFF_CODE)
It gives the error:
single-row subquery returns more than one row.
How to solve this?
Change = to IN:
WHERE SM.STAFF_CODE IN (SELECT ...)
Because the select returns multiple values, using equals won't work, but IN returns true if any of the values in a list match. The list can be a hard-coded CSV list, or a select with one column like your query is.
That will fix the error, but you also need to remove BOOK_TRANSACTIONS from the table list and remove BOOK_CODE from the select list.
After making these changes, your query would look like this:
SELECT SM.STAFF_CODE,SM.STAFF_NAME,DM.DEPT_NAME
FROM STAFF_MASTER SM,DEPARTMENT_MASTER DM
WHERE SM.DEPT_CODE =DM.DEPT_CODE
AND SM.STAFF_CODE IN (
SELECT STAFF_CODE
FROM BOOK_TRANSACTIONS
HAVING COUNT(*) > 1
GROUP BY STAFF_CODE)
I recommend learning the modern (now over 25 year old) JOIN syntax.

Help with complex mysql query

I have an existing mysql query that I need to add to and I'm not sure how to go about it.
Here is my current sql query.
SELECT tbl_brokerage_names.brokerage_id, tbl_brokerage_names.short_name,
b.indication, b.max_indication
FROM tbl_brokerage_names
LEFT JOIN (
SELECT * FROM tbl_recommendation_brokerages
WHERE recommendation_id = {$_GET['id']}
) b ON (tbl_brokerage_names.brokerage_id = b.brokerage_id)
ORDER BY tbl_brokerage_names.short_name ASC
Here is the query that I need to work into the previous query.
SELECT * , COUNT( * )
FROM tbl_streetaccounts
JOIN tbl_brokerage_names
WHERE tbl_brokerage_names.brokerage_id = tbl_streetaccounts.brokerage_id
Basically I need to return a count, so I need to combine these two queries.
You should run these as two separate queries.
The COUNT(*) query will return a single row, so there's no way to "combine" it with the first query while preserving the multi-row result of the first query.
Also, when you SELECT *, COUNT(*) you will get columns from some arbitrary row.
By the way, you have a glaring SQL injection vulnerability. Don't interpolate $_GET parameters directly in your SQL query. Instead, coerce it to an integer:
<?php
$id = (int) $_GET['id'];
$sql = "SELECT ... WHERE recommendation_id = {$id}";
Like #Bill said, you cannot get the count in every row without really weird syntax, but you can get an overall count using GROUP BY ... WITH ROLLUP.
e.g.:
<?php
$id = mysql_real_escape_string($_GET['id']); //works with anything, not just numbers
$query = "
SELECT tbl_brokerage_names.brokerage_id
, tbl_brokerage_names.short_name
, b.indication
, b.max_indication
, count(*) as rowcount
FROM tbl_brokerage_names
LEFT JOIN (
SELECT * FROM tbl_recommendation_brokerages
WHERE recommendation_id = '$id' //The single quotes are essential for safety!
) b ON (tbl_brokerage_names.brokerage_id = b.brokerage_id)
GROUP BY tbl_brokerage_names.brokerage_id WITH ROLLUP
ORDER BY tbl_brokerage_names.short_name ASC
";
The GROUP BY .. WITH ROLLUP will add an extra line to the result with all NULL's for the non aggregated columns and a grand total count.
If you have any lines where rowcount > 0 then you need to add extra clauses from table b to the group by clause to prevent MySQL from hiding arbitrary rows.
Table tbl_brokerage_names is already fully defined because you are grouping by the primary key.

MySQL group by x characters on an id field

I have a client database that is in a pretty poor state, but I have to work with it. We have a set of product id's and each id is made up of the attributes of the product. What i'd like to do is select those id's that match the first 4 or 5 characters and have them in a drop down box as variants of a selected product.
I've tried 'group by subtr(0,6)', but this seems to return only the first match in the group. What I need is to have separate queries, that ONLY return ALL the individual rows that have a matching first x characters.
So, for example, I want to have queries that will return:
12345xx
12345yy
12345zz
and then another that will return:
56789xx
56789yy
56789zz
This following query would return only:
12345xx
and then
56789yy for example
select tbl_item.Description, tbl_item.`Description 2`, tbl_item.`Inventory Posting Group`, tbl_item.No_, tbl_item.`Web Description`, tbl_item.`Web Headers`, tbl_item.`Unit Price`, tbl_item.`Sales (Qty_)`, tbl_item.`Product Group Code`
from tbl_item
where tbl_item.`Product Group Code` = ':shopprodid' and tbl_item.`Vendor No_` = '$vendor_no'
group by substr(0,6)
The solution is to put the substr and LIKE in the WHERE clause (no need to group anything). And btw, in MySql the substring starts at index 1, not 0.
select *
from tbl_item
where substr(tbl_item.`Product Group Code`, 1, 6) LIKE ':shopprodid%'
What do you mean by substr(0,6)? the correct syntax is
SUBSTR( str, pos, len )
I suppose you mean:
SUBSTR( tbl_item.id, 0, 6 )
correct that.
And for the results you want you don't need the substr at all, use a query like this:
SELECT * from tbl_item WHERE tbl_item.id LIKE '12345%'
Try something like the following;
SELECT * FROM tbl_item WHERE SUBSTR([<Column name>], 1, 6) = '<Your ID prefix>' ORDER BY [<Column name>]