groupby query by year - mysql

shipwynum is the primary key for convertship table.
Actually this query getting data correct, for year 2008 only. When i replace 2008 with any other year then also getting data correct for that year. This query display the total records for that year not in TotalCount. TotalCount has always one becoz i have group by with shipwynum.
But i want to get data for 1000 to 2011 separately(instead a particular year like 2008) in this one query and TotalCount should display the counts for every year.
I have this query :=
select
distinct
count(con.shipwynum) as TotalCount,
con.shipwynum,
s.deldat,
s.deldat as DeliveryQuarter,
left(s.deldat,4) as DelYear
from convertship con
left join shipscheduled s on con.shipwynum = s.shipwynum and s.deleted = 'N'
where left(s.deldat,4) > 1000 and left(s.deldat,4) <= 2008 and
left(con.condat,4) > 2008 and
con.deleted = 'N' and
con.wytypid in ('66', '10', '11', '12', '13', '14', '15', '16', '17','18') and
s.wytypid not in ('66', '10', '11', '12', '13', '14', '15', '16', '17','18')
group by con.shipwynum
Any help or ideas would be greatly appreciated.
Thanks a lot.

I think you're trying to count number of rows for each year?
From what i assume,
there is one main table convertship and you want to join convertship to shipscheduled.
Then do the group by on that data according to its left(con.condat,4) value.
select distinct
count(con.shipwynum) as TotalCount,
con.shipwynum,
s.deldat,
s.deldat as DeliveryQuarter,
left(s.deldat,4) as DelYear,
left(con.condat,4) as ConYear
from
convertship con
inner join
shipscheduled s on con.shipwynum = s.shipwynum
where
left(s.deldat,4) > 1000 and
left(s.deldat,4) <= 2008 and
-- left(con.condat,4) > 2008 and
con.deleted = 'N' and
s.deleted = 'N' and
con.wytypid in ('66','10','11','12','13','14','15','16','17','18') and
s.wytypid not in ('66','10','11','12','13','14','15','16','17','18')
group by
left(con.condat,4)
I assume the convertship table is not too big, if not this will not work.

Try:
select count(con.shipwynum) as TotalCount,
con.shipwynum,
s.deldat,
s.deldat as DeliveryQuarter,
left(s.deldat,4) as DelYear
from convertship con
left join shipscheduled s
on con.shipwynum = s.shipwynum and
s.deleted = 'N' and
left(s.deldat,4) > 1000 and
left(s.deldat,4) < left(con.condat,4) and
s.wytypid not in ('66', '10', '11', '12', '13', '14', '15', '16', '17','18')
where con.deleted = 'N' and
con.wytypid in ('66', '10', '11', '12', '13', '14', '15', '16', '17','18') and
group by con.shipwynum, left(s.deldat,4)
Note that since deldat and DeliveryQuarter are neither grouped by nor aggregated, their values in the output will essentially be random (within the DelYear).

Related

SQL query to get number of clients with last statement equal connected

I need to make a SQL query
table 'records' structure:
contact_id(integer),
client_id(integer),
worker_id(integer),
statement_status(varchar),
contact_ts(timestamp)
It has to show the following:
current date
number of clients which last statement_status was 'interested'
number of clients which last statement_status was 'not_interested' and previus status was 'not_present'
Could somebody help?
sample data:
contact_id client_id contact_ts worker_id statement_status
'1', '181', '2017-09-24 03:38:31.000000', '107', 'voicemail'
'2', '72', '2017-09-23 09:32:38.000000', '10', 'not_interested'
'3', '277', '2017-09-22 07:06:16.000000', '119', 'interested'
'4', '36', '2017-09-21 04:39:57.000000', '118', 'not_present'
'5', '33', '2017-09-20 04:12:12.000000', '161', 'voicemail'
'6', '244', '2017-09-19 02:26:30.000000', '13', 'not_interested'
'7', '346', '2017-09-18 02:30:35.000000', '255', 'interested'
'8', '128', '2017-09-17 06:20:13.000000', '52', 'not_present'
'9', '33', '2017-09-16 08:58:02.000000', '188', 'not_present'
'10', '352', '2017-09-15 08:18:40.000000', '324', 'not_interested'
'11', '334', '2017-09-14 04:27:40.000000', '373', 'interested'
'12', '2', '2017-09-13 08:44:40.000000', '40', 'not_present'
'13', '33', '2017-09-12 03:46:16.000000', '252', 'voicemail'
'14', '366', '2017-09-11 04:31:22.000000', '78', 'not_interested'
'15', '184', '2017-09-10 06:08:01.000000', '289', 'interested'
'16', '184', '2017-09-09 05:45:56.000000', '124', 'not_present'
'17', '102', '2017-09-08 07:09:30.000000', '215', 'voicemail'
'18', '140', '2017-09-07 08:09:18.000000', '196', 'not_interested'
'19', '315', '2017-09-06 05:13:40.000000', '242', 'interested'
'20', '268', '2017-09-05 07:41:40.000000', '351', 'not_present'
'21', '89', '2017-09-04 05:32:05.000000', '232', 'voicemail'
desired output:
Time, interested, not-interested
2017-09-10 06:08:01, 5, 5
I tried something with sub queries, but it obviously doesn't work:
SELECT
GETDATE()
,(select count(*)
from record a
where (select statement_status
from record
where client_id == a.client_id
order by a.contact_ts
limit 1) == "interested"
group by a.contact_id)
,(select count(*)
from record a
where (select (select statement_status
from record
where client_id == a.client_id
order by a.contact_ts
limit 2) order by a.contact_ts desc limit 1) == "interested"
and
(select statement_status
from record
where client_id == a.client_id
order by a.contact_ts
limit 1) == "interested"
group by a.contact_id)
from record b;
How should I use the inner selects?
I must write a poem, because most of my post is a code.
So maybe something from "Dead man"?
“Don't let the sun burn a hole in your ass, William Blake. Rise now, and drive your cart and plough over the bones of the dead!”
;)
Try something like this:
WITH status AS (
SELECT DISTINCT client_id,
first_value(statement_status) OVER w1 AS last_status,
nth_value(statement_status, 2) OVER w1 AS prev_status
FROM records
WINDOW w1 AS (PARTITION BY client_id ORDER BY contact_ts DESC RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
)
SELECT CURRENT_DATE(),
SUM(last_status = 'interested') AS interesed,
SUM(last_status = 'not_interested' AND prev_status = 'not_present') AS not_interested
FROM status

how to get data weekly wise in mysql for each month

SELECT DATE_FORMAT(es.scheduled_datetime, '%X-%V') AS date,
COUNT(es.event_schedule_id) AS total,
0 as type
FROM event_schedule es ,event_schedule_mapping esm,events e
WHERE
es.event_schedule_id = esm.event_schedule_id and
esm.event_id = e.event_id and
es.event_status_id in(1,2) and
es.scheduled_datetime BETWEEN
'2017-01-01' AND '2017-01-31'
GROUP BY date
ORDER BY date
this is my Query using this Query i am able to display record whose count is greater than zero and below output come like this
for January month
'2017-01', '2', '0'
'2017-02', '2', '0'
'2017-03', '10', '0'
'2017-04', '2', '0'
'2017-05', '9', '0'
But its not displaying if count is zero in second week while i have to
display that also :
'2017-01', '2', '0'
'2017-02', '0', '0'
'2017-03', '10', '0'
'2017-04', '2', '0'
'2017-05', '9', '0'
please suggest me how to display Record if count is zero it should week wise please suggest me
if you want to get data weekly in each month from database , I have query for that try this query.
SELECT DISTINCT EXTRACT(WEEK FROM date) as week,tbl_data.date AS date, SUM(count.calories) AS sum,tbl_data.offset AS offset from tbl_data INNER JOIN count ON count.id = tbl_data.item_id where tbl_data.user_id="+user_id+" and tbl_data.date and MONTH(date) = MONTH(CURRENT_DATE()) GROUP BY week

MYSQL issue howto count result in master table not including all rows from a Detail table "labels" used in a join

To simplify the question I am only using a few field in my test table example
Master db
Id Description type cost
'1', 'Test1', '2', '100'
'2', 'Test2', '2', '100'
'3', 'Test3', '3', '100'
'4', 'Test4', '4', '100'
Labels db
ID Name Masterid
'1', 'Label1', '1'
'2', 'Label1', '2'
'3', 'Label2', '1'
'4', 'Label3', '1'
I would like to count all ID's and make summary for the cost field for all records in master containing label1 and label2 from labels
My Query
Select count(Distinct m.id) as andtall , sum(m.cost) as cost
from
master m
join labels l ON l.Masterid=m.id and l.name in ('Label1','Label2')
Since I am using Distinct in count that result will be correct, but Cost is wrong it's containg 3 records not 2.
'2', '300' I would like it to return 200 since only 2 records from master table should be returned.
Try this
SELECT
count( m.id ) as andtall,
sum( m.cost ) as cost
FROM
master m
JOIN (
SELECT
Masterid
FROM
labels l
WHERE
l.name in ('Label1', 'Label2')
GROUP BY master_id ) l ON l.Masterid = m.id

SQL query to show top x records with evenly distributed values

I have a database of contacts at companies. Multiple contacts per company in different departments. Each company has turnover and industry data attached to it.
I need to write a query that shows the top 10 most recently added contacts (unix timestamp) but i don't want it to be all Marketing contacts (even if the top 10 are), i would like to look at the top 100 instead and get 10 contacts out that are from different departments. So instead of the top 10 being all marketing, there might be 2 marketing, 2 I.T, 2 HR, 2 Personnel.
So my query basically is this:
SELECT DISTINCT `surname`, `job_title`, `company_name`
FROM (`company_database`)
WHERE `employee_code` IN ('6', '7', '8', '9', '10', '11', '12', '13')
AND `turnover_code` IN ('5', '6', '7', '8')
AND `contact_code` IN ('16', '17', '26', '27', '9', '10', '30', '31', '23', '24', '12', '13') AND `industry_code` NOT IN ('22', '17', '35', '36') LIMIT 10
But that simply returns a unique row. What i need is one contact per company and no more than 1 contact_code type. I also only want 10 rows returned, but obviously to get this 1 per contact code per row, the query will need to look at more than 10.
Is this possible in just a query? Or should i do something programatically to apply the logic needed to whittle down the results of a query.
you can work with a temporary table using the myisam engine and a trick.
If you create the following temporary table:
create table tmp_company_sequence
( surname varchar(255)
,job_title varchar(255)
,company_name varchar(255)
,date_added date
,contact_code int
,counter int auto_increment
,primary key (contact_code,counter)
);
Now
insert into `tmp_company_sequence`( `surname`, `job_title`, `company_name`,`contact_code`,`date_added`)
SELECT DISTINCT `surname`, `job_title`, `company_name`,`contact_code`,`date_added`
FROM (`company_database`)
WHERE `employee_code` IN ('6', '7', '8', '9', '10', '11', '12', '13')
AND `turnover_code` IN ('5', '6', '7', '8')
AND `contact_code` IN ('16', '17', '26', '27', '9', '10', '30', '31', '23', '24', '12', '13') AND `industry_code` NOT IN ('22', '17', '35', '36')
order by contact_code, added_date desc;
Your temporary table will now hold all the contacts with a counter. The counter is increased for every contact of the same contact_code. SO the newest contact with a certain contact code will have counter = 1, the next recent will have counter = 2 and so on.
You can now do a
select *
from tmp_company_sequence
order by counter asc, date_added desc
limit 10;
This will give you a list of the latest contacts added over all contact_codes.
Edit:
I just realised this could be done with a single query, but it is even more ugly:
SELECT `surname`
, `job_title`
, `company_name`
, `contact_code`
FROM(
SELECT
`surname`
, `job_title`
, `company_name`
, `contact_code`
, `date_added`
, IF(contact_code = #prev_contact_code,#i:=#i+1,#i:=1) AS counter
, #prev_contact_code = contact_code
FROM
(`company_database`)
,(SELECT #i := 1)
WHERE `employee_code` IN ('6', '7', '8', '9', '10', '11', '12', '13')
AND `turnover_code` IN ('5', '6', '7', '8')
AND `contact_code` IN (
'16'
, '17'
, '26'
, '27'
, '9'
, '10'
, '30'
, '31'
, '23'
, '24'
, '12'
, '13'
)
AND `industry_code` NOT IN ('22', '17', '35', '36')
ORDER BY contact_code
, added_date DESC) sub
WHERE counter = 1
ORDER BY added_date DESC
LIMIT 10;
This does basically the same as the option with the temporary table, but it creates the counter in the fly by storing data from the previous column in global variables. It is messy but can be used within a single query.

mysql group_concat order by utf8

I have the following problem
I have 3 table (all of the are used utf8 / utf8_general_ci encoding)
movies, channels, i also have 3 table movie_channels which
is just a combination of the other two with just 2 fields: movie_id,channel_id
here is my channels table (code,name)
'1', 'ОРТ'
'2', 'ТК Спорт'
'3', 'ТК ТНВ'
'4', 'НТВ'
'5', 'НТВ+'
'6', 'TSN'
here is my movie_channels table (movie _id, channel_id) channel_id references code field in channels table
'19', '2'
'19', '6'
'95', '1'
'95', '4'
'96', '1'
'96', '4'
'97', '1'
'97', '4'
'98', '1'
'98', '4'
'99', '1'
'99', '4'
'100', '1'
'100', '4'
don't mind quotes on id values. they are all ints of course, not chars, it's just pasting issue
for each movie i need to display comma separated list of channels
i used mysql group_concat
select t.movie_id,( select group_concat(c.name) from
movie_channels mc
join channels c on mc.channel_id=c.code
where mc.movie_id = t.movie_id
order by code desc )as audio_channel from movies t
but I dont like the order of concat for movie_id #19 i need the above sql to display TSN,ТК Спорт but it keeps returning me ТК Спорт,TSN . I tried to use order by code desc with no luck ,tried order by char_length(asc) with no success
any ideas ?
If for every movie you want to list all the channels that are showing that movie, you need something like this:
SELECT
mc.movie_id,
GROUP_CONCAT(c.name) AS channels
FROM movie_channels AS mc
JOIN channels AS c
ON c.code = mc.channel_id
GROUP BY mc.movie_id
ORDER BY c.code DESC;
You can add a ORDER BY clause inside the GROUP_CONCAT() aggregate to adjust the ordering of the grouped string.