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
Related
I have 2 mysql tables:
record table:
and
race table:
I want to select the records from the 1st table group by id_Race but only the MAX from column "secs".
I tried the following but didnt work:
$query = "SELECT rec.RecordsID,rec.id_Athlete,rec.date_record,rec.id_Race,rec.placeevent,rec.mins,rec.secs,rec.huns,rec.distance,rec.records_text,r.name,MAX(rec.secs)
FROM records AS rec INNER JOIN race AS r ON r.RaceID=rec.id_Race WHERE (id_Athlete=$u_athlete) GROUP BY rec.id_Race;";
($u_athlete is a variable i get from _SESSION)
Can you help me about that?
Thank you.
When you use an aggregation function like MAX and select all fields, you are forced to include all selected fields that are not affected by the MAX inside the GROUP BY clause.
Though you can use a window function like ROW_NUMBER that will group by specifically on id_Race and order by the secs column in a descendent way (so that the highest value of secs will be associated with row_number=1).
Afterwards you can select the rows which have row_number=1 and the id_Athlete you pass using the variable.
SELECT
rec.RecordsID,
rec.id_Athlete,
rec.date_record,
rec.id_Race,
rec.placeevent,
rec.mins,
rec.secs,
rec.huns,
rec.distance,
rec.records_text,
race.name,
FROM
(
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY id_race ORDER BY secs) rank
FROM
record
) rec
INNER JOIN
race race
ON
race.RaceID=rec.id_Race
WHERE
rec.rank = 1
AND
rec.id_Athlete = $u_athlete;
I am trying to make a request where I select from an array of value using the IN, but inside this array, if I have the same value twice, I'd like the request to return the result twice.
To clarify, here is an example:
select id_exo, count(id_exo) FROM BLOC WHERE id_seance IN (10,10) group by id_exo
So inside the IN, I put 2 times the value 10.
Here is the result:
id_exo
count(id_exo)
60
1
82
1
But in count, I'd like to have the number 2 since I have put twice 10 inside my IN.
How can I achieve that?
SELECT id_exo, COUNT(id_exo)
FROM bloc
JOIN (SELECT 10 id_seance
UNION ALL
SELECT 10) val USING (id_seance)
GROUP BY id_exo
Prior to MySQL 8.0 you can join with a sub select:
select * from BLOC as b
inner join (
select 1 as 'id', 10 as 'value'
union
select 2,10
union
select 3,10) as myValues on myValues.value = b.id_seance
You need the id column as the UNION statement removes duplicate rows
If you are lucky enough to have MySQL 8.0 look at the VALUES statement
https://dev.mysql.com/doc/refman/8.0/en/values.html
Here you should instead be able to join with something like
VALUES ROW(10), ROW(10), ROW(10)
I've a MY-SQL query which is pulling a set of records from database. I want to aggregate slightly different way to use in my application. When duplicate rows present in record set with same ticker value query will sum up est_units and est_trans_value and display in new columns as total_est_units and total_est_trans_value. If there is no duplicate with same ticker value it should display total_est_units as est_units and total_est_trans_value as est_trans_value. How can I do this -- Can you please help to modify this query?
SQL:
SELECT
oc.*
FROM
order_confirm_daily oc
INNER JOIN
(SELECT
id, ticker, MAX(est_order_time) AS mts
FROM
order_confirm_daily
WHERE DATE(est_order_time) LIKE '2021-04-26%'
GROUP BY ticker) ds ON ds.ticker = oc.ticker
AND oc.est_order_time = ds.mts;
Sample Data:
desired results: Added two new derived column "total_est_units" and "Total_est_trans_value" which will display Sum of est_units and est_trans_value respectively only when multiple rows present with same ticker -- here it is "TNA" highlighted in screen shot.
I see. You just want window functions:
select oc.*,
sum(est_units) over (partition by ticker) as total_est_units,
sum(est_trans_value) over (partition by ticker) as total_est_trans_value
from order_confirm_daily oc;
EDIT:
In older versions of MySQL, you would use JOIN and GROUP BY:
select *
from order_confirm_daily oc join
(select ticker, sum(est_units) as total_est_units,
sum(est_trans_value) as total_est_trans_value
from order_confirm_daily oc
group by ticker
) oct
using (ticker);
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 ;
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.