I have one table with this headers
id city date item
I am interested in identify the id with the same item in the same month and count how many items repeated receive in the same month. So my query in mysql is:
select a.id, concat(a.id, month(a.date), a.item) as a from table
where a = (select concat(b.id, month(b.date), b.item) as b from table)
group by a.id
having count(a=b)>=1
But that query take too much time and may not work, could you help me?
You haven't reacted to the comments made three hours ago. But from your comments to Seth McClaine's answer I read that you want a list of rows showing id (which despite its name is not the table's unique ID!), month, item, and the number of occurences.
One row per id, month and item means: group by id, month, item.
Use a HAVING clause in order to only show occurences > 1.
select id, month(date), item, count(*)
from mytable
group by id, month(date), item
having count(*) > 1;
Well, this is about what Seth McClaine already told you. And while you commented on his answer, you didn't say what is missing from it for you to accept it.
I think you should be able to do something like this, giving you the count total of items with matching id, month, and item
Select Count(*) as total, month(date) as month, item, id
From table
group by (item, month(date), id)
Related
I want to count how many exact values appear in the week of the year, I know the result will be in the next column but this is ok. I want to count how many X's, Y's and Z's are in the exact week of the year.
In the picture you can find what I wanted to achieve - last column:
Note: COUNT(1) OVER (PARTITION BY WEEK) - Counts how many X's, Y's and Z'(in overall) I have in the Particular Week, but also I want to know how many each of them is in the particular week.
I tried to write subquery but without the result, I don't know how to calculate the values that occur in a particular week also
I wanted to Use Sum(case When Then) but I could not figure it out how to do that.
Excel is so much easier to handle this
This is what I wrote:
SELECT
A.number,
B.flag_value,
B.add_data,
COUNT(1) OVER (PARTITION BY B.flag_value) flgcnt,
DatePart("ww",Add_data) AS Week_NO,
COUNT(1) OVER (PARTITION BY WEEK)
FROM table A AS "A"
LEFT JOIN table B AS "B" ON A.id = B.source_id
WHERE
GROUP BY A.number, B.flag_value
Thank you in advance
This question already has answers here:
Retrieving the last record in each group - MySQL
(33 answers)
Closed 10 months ago.
Above is the table and on the basis of which I have to answer the below question in my past interview.
Q. The most recent order value for each customer?
Answer which I have given in interview:
select customerID, ordervalue, max(orderdate)
from office
group by customerID;
I know since we are not using ordervalue in aggregate and nor in group by so this query will throw an error in SQL but I want to know how to answer this question.
Many times in my past interviewers asked a question where I need to use a column in select statement which is not in aggregate function or nor in group by. So I want know in general what is a workaround for it with an example so that I can resolve these type of questions or how to answer these questions.
The work around depends on what is being asked. For the requirements you have above, I think it makes sense to create (customerid, MAX(orderdate)) pairs.
SELECT customerid, MAX(orderdate)
FROM office
GROUP BY customerid;
Then you can use them to match the row you need from the table.
SELECT customerid, ordervalue, orderdate
FROM office
WHERE (customerid, orderdate) IN
(SELECT customerid, MAX(orderdate)
FROM office
GROUP BY customerid);
Note, this assumes there is only one order per customer per day. If there were more than one, you would see the most recent order(s) per customer. You could add also a GROUP BY on the outer query if needed.
SELECT customerid, MAX(ordervalue), orderdate
FROM office AS tt
WHERE (customerid, orderdate) IN
(SELECT customerid, MAX(orderdate)
FROM office
GROUP BY customerid)
GROUP BY customerid, orderdate;
If the non-aggregate column you need in the SELECT is functionally dependent on the column in the GROUP BY, you can add a subquery in the SELECT.
We can extend your example by adding a name column, where the name of different customers could be the same. If you wanted name instead of ordervalue, just match the customerid of the outer query to get name.
SELECT customerid,
(SELECT name FROM office WHERE customerid=o.customerid LIMIT 1) AS name,
MAX(orderdate)
FROM office AS o
GROUP BY customerid;
You are approaching the task as follows: Aggregate all rows to get one result line per customer, showing the maximum order date and its order value. The problem with this: you'd need an aggregate function to get the value for the maximum order date. The only DBMS I know of featuring such a function is Oracle with KEEP FIRST/LAST.
So look at the task from a different angle. Don't think aggregation-wise where you could count and add up values for a group and get the minimum or maximum value over all the group's rows, because after all you just want to pick single rows. (That is, pick the top 1 row per customer.) In order to pick rows, you'll use a WHERE clause.
One option has been shown by Steve in his answer:
select *
from office
where (customerid, orderdate) in
(
select customerid, max(orderdate)
from office
group by customerid
);
This is a good, straight-forward approach. (Some DBMS, though, don't feature tuples with IN clauses.)
Another way to get the "best" row for a customer would be to pick those rows for which not exists a better row:
select *
from office
where not exists
(
select null
from office better
where better.customerid = office.customerid
and better.orderdate > office.orderdate
);
And then there is the option to use a window function (aka analytic function) in order to get those rows. One example is to get the maximum dates along with the rows' data:
select customerid, ordervalue, orderdate
from
(
select
customerid, ordervalue, orderdate,
max(orderdate) over (partition by customerid) as max_orderdate
from office
)
where orderdate = max_orderdate;
And with ROW_NUMBER, RANK, and DENSE_RANK there are window functions to assign numbers to your rows in the order you want. You number them such that the best rows get number 1 and pick them. The big advantage here: you can apply any order, deal with ties and not only get the top 1, but the top n rows.
select customerid, ordervalue, orderdate
from
(
select
customerid, ordervalue, orderdate,
row_number() over (partition by customerid order by orderdate desc) as rn
from office
)
where rn = 1;
Supposed I have a SQL table that looks like this
Now I am suppose to do this 'logic' so that I know that on 23/6/2017, the word 'accessories' appeared 2 times and 'tools' appeared 1 time.
I think there is some kind of way to do this is mysql, something along the lines of COUNT() and GROUPBY but I cannot get the result I want.
Appreciate any guidance. Thanks!
You can do this by using GROUP BY :
SELECT date, category, count(*) as count FROM table_name GROUP BY date, category
You have to put every selected columns after group by otherwise it will show query error.
SELECT date, category, count(*)
FORM yourtable
GROUP BY date, category
It's as simple as counting the categories corresponding to each date
SELECT date
category
COUNT(*)
FROM table_name
GROUP BY date, category
I have a very basic table, consisting of an integer column and a timestamp column.
What's the query to count how many entries there are for each day?
When I use SELECT COUNT(*) FROM taps GROUP BY(DATE(time_stamp)) , I get the total number of rows int he table, rather than the number of rows for each DISTINCT date.
How do I need to modify the query?
Pretty straightforward.
SELECT
DATE(time_stamp),
COUNT(1)
FROM taps
GROUP BY DATE(time_stamp)
I have a voting application that writes values to a mysql db table. It is a preference/weighted voting system so people choose a first option, second option, and third option. These all go into separate fields in the table. I'm looking for a way to write a query that will assign numerical values to the responses (3 for a first response, 2 for a second, 1 for a first) and then display the value with the summed score. I've been able to do this for total number of votes
select count(name) as votes,name
from (select 1st_option as name from votes
union all
select 2nd_option from votes
union all
select 3rd_option from votes) as tbl
group by name
having count(name) > 0
order by 1 desc;
but haven't quite figured out how to assign values to response in each column and then pull them together. Any help is much appreciated. Thanks!
You could do something like this:
select sum(score) as votes,name
from (select 1st_option as name, 3 as score from votes
union all
select 2nd_option as name, 2 as score from votes
union all
select 3rd_option as name, 1 as score from votes) as tbl
group by name;