Extend Mysql table for same id - mysql

My table structure is:
id | type | attribute | customer_id | value
1 | 2 | 1 | 1 | some
2 | 2 | 2 | 1 | this
3 | 2 | 3 | 1 | that
4 | 2 | 1 | 2 | cool
5 | 2 | 2 | 2 | just
etc
I want to add value='mine' as attribute 4 to each customer_id.
INSERT INTO mytable
SET type='2', attribute='4, value='mine'
The question is how to bind it on customer_id and only once per customer?

INSERT INTO myTable(type, attribute, customer_id, value)
SELECT 2 type,
4 attribute,
s.customer_id,
'mine' `value`
FROM (SELECT DISTINCT customer_id FROM myTable) s

Related

MySQL - select results from a secondary table as a column in a primary table

I have a set of data consisting of two tables: table one is a set of unique items, and table two is a log of references that link the items in the first table together. For example:
Table one
+------------+--------------------+
| id | name |
+------------+--------------------+
| 1 | Item 1 |
| 2 | Item 2 |
| 3 | Item 3 |
| 4 | Item 4 |
| 5 | Item 5 |
+------------+--------------------+
Table two
+------------+--------------------+
| item_1_id | item_2_id |
+------------+--------------------+
| 1 | 2 |
| 1 | 3 |
| 1 | 5 |
| 2 | 4 |
| 2 | 5 |
+------------+--------------------+
Is it possible to group the rows that are in table two, and display them in some sort of array/collection as a column in table one. So based on my example tables, I would hope to return something like this:
+------------+-----------+----------+
| id | name | results |
+------------+-----------+----------+
| 1 | Item 1 | 2, 3, 5 |
| 2 | Item 2 | 1, 4, 5 |
| 3 | Item 3 | 1 |
| 4 | Item 4 | 2 |
| 5 | Item 5 | 1, 2 |
+------------+-----------+----------+
You can use group_concat for show the aggregated result and a select union for obtain both the related item for grouping
select id, name, group_concat( item1)
from table_one
left join
(select item_1_id as item1, item_2_id as item2
from table_two
union
select item_2_id , item_1_id
from table_two
order by item1) t1 ont1.item1 = table_one.id
group by id, name

MySQL SUM and GROUP BY from AS column

table1 structure and sample data
+----+-------------+----------+------+-------+
| ID | DESCRIPTION | QUANTITY | EACH | PRICE |
+----+-------------+----------+------+-------+
| 1 | Product 1 | 1 | 12 | 1*12 |
| 2 | Product 2 | 2 | 3 | 2* 3 |
| 3 | Prodcut 3 | NULL | 3 | |
| 4 | Product 1 | 2 | 10 | 2*10 |
| 5 | Product 3 | NULL | 7 | |
+----+-------------+----------+------+-------+
MySQL query:
SELECT
DESCRIPTION,
QUANTITY,
EACH,
COALESCE(QUANTITY, 1) * EACH AS PRICE
FROM table1
GROUP BY DESCRIPTION
How could I make SUM for the PRICE column and GROUP BY the DESCRIPTION column? I don't want to use UPDATE because I can't change the values in the table1.
Well why can't you add SUM(COALESCE(QUANTITY, 1) * EACH) AS PRICETOTAL in your select list.
SELECT
DESCRIPTION,
SUM(COALESCE(QUANTITY,1)*each) as 'Price'
FROM table1
GROUP BY DESCRIPTION
returns
DESCRIPTION Price
Product 1 32
Product 2 6
Product 3 10

How to create a simple crosstab query in MySQL

I have two tables containing fields as below.
Table 1
| SetID | InQty | Day |
| 1 | 10 | 1 |
| 2 | 10 | 2 |
| 3 | 10 | 3 |
Table 2
| SetID | OtQty | Day |
| 1 | 1 | 5 |
| 1 | 2 | 6 |
| 1 | 3 | 7 |
SetID in table 2 is linked with SetId in table 1. Day is placed in place of date, just for convenience only. Expected Output,
| Day | InQty | OtQty |
| 1 | 10 | |
| 5 | | 1 |
| 6 | | 2 |
| 7 | | 3 |
Blank Space can be filled with NULL or Zero.
It appears you are querying ONLY for set ID = 1 otherwise, I would expect to see in/out values for Set 2 and 3. You should be able to get with a simple UNION
select t1.Day, t1.InQty, 0 OutQty
from Table1 t1
where SetID = 1
order by t1.Day
union select t2.Day, 0, t2.OtQty
from Table2 t2
where SetID = 1
Now, if you want totals spanning different "setID"s and keeping them differentiated from each other, just add the setID as a column and also add to the group by clause as well.

SQL, difficult fetching data query

Suppose I have such a table:
+-----+---------+-------+
| ID | TIME | DAY |
+-----+---------+-------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 1 | 1 | 2 |
| 2 | 2 | 2 |
| 3 | 3 | 2 |
| 1 | 1 | 3 |
| 2 | 2 | 3 |
| 3 | 3 | 3 |
| 1 | 1 | 4 |
| 2 | 2 | 4 |
| 3 | 3 | 4 |
| 1 | 1 | 5 |
| 2 | 2 | 5 |
| 3 | 3 | 5 |
+-----+---------+-------+
I want to fetch a table which represents 2 IDs which got the largest sum of TIME within the last 3 days (means from 3 to 5 in a DAY column)
So the correct result would be:
+-----+---------+
| ID | SUM |
+-----+---------+
| 3 | 9 |
| 2 | 6 |
+-----+---------+
The original table is much larger and more complex. So i need a generic approach.
Thanks in advance.
And so I just learned that MySQL used LIMIT instead of TOP...
fiddle
CREATE TABLE tbl (ID INT,tm INT,dy INT);
INSERT INTO tbl (id, tm, dy) VALUES
(1,1,1)
,(2,2,1)
,(3,3,1)
,(1,1,2)
,(1,1,1)
SELECT ID
,SUM(SumTimeForDay) SumTimeFromLastThreeDays
FROM (SELECT ID
,SUM(tm) SumTimeForDay
FROM tbl
GROUP BY ID, dy
HAVING dy > MAX(dy) -3) a
GROUP BY id
ORDER BY SUM(SumTimeForDay) DESC
LIMIT 2
select t1.`id`, sum(t1.`time`) as `sum`
from `table` t1
inner join ( select distinct `day` from `table` order by `day` desc limit 3 ) t2
on t2.`da`y = t1.`day`
group by t1.`id`
order by sum(t1.`time`) desc
limit 2

SQL Group by using the First N elements in each group [duplicate]

This question already has an answer here:
Top N per Group Sql problem in mysql
(1 answer)
Closed 9 years ago.
Suppose I have the next table:
+------------+---------+
| MovieId | rating |
+------------+---------+
| 1 | 4 |
| 1 | 3 |
| 1 | 2 |
| 1 | 4 |
| 1 | 5 |
| 2 | 3 |
| 2 | 4 |
| 2 | 2 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 3 | 5 |
| 4 | 4 |
| 4 | 2 |
+------------+---------+
I would like to get the average by group BUT using the first 2 elements on each group.
Example:
+------------+---------+
| MovieId | rating |
+------------+---------+
| 1 | 4 |
| 1 | 3 |
| 2 | 3 |
| 2 | 4 |
| 3 | 1 |
| 3 | 2 |
| 4 | 4 |
| 4 | 2 |
+------------+---------+
answer expected:
+------------+---------+
| MovieId | AVG |
+------------+---------+
| 1 | 3.5 |
| 2 | 3.5 |
| 3 | 1.5 |
| 4 | 3 |
+------------+---------+
This is the SQL query I have to get the AVG for all of the movies. But as I said, I would like to use just the first 2 elements for each group.
SELECT movieid, AVG(cast(rating as DECIMAL(10,2))) AS AVG
FROM ratings
group by movieid
If you can help me to make the SQL I appreciate. I will also use Linq just in case some of you know it.
In a SQL DBMS -- as in the relational model -- there is no "first". Do you mean any arbitrary 2 rows for each movie, or the two highest ratings, or something else?
If you can't define an order, then the query is meaningless.
If you can define an order, join the table to itself as I show in my canonical example to create a ranking, and select where RANK < 3.
FOR Mysql:-
select id, avg(rating)
from (SELECT a.*, #num := #num + 1 rownum,
(select count(*)
from movies m
where m.id<=a.id) last_count,
(select count(*)
from movies m1
where a.id=m1.id) grp_count
from movies a, (SELECT #num := 0) d) f
where grp_count-(last_count-rownum)<=2
group by id;
you can use rownum function in oracle. And row_number() function in sql server.
This is a solution in SQL
Create table #tempMovie (movieId int ,rating int)
INSERT INTO #tempMovie
Select * from table where movieidid=1 Limit 2
Union all
Select * from table where movieidid=2 Limit 2
Union all
Select * from table where movieidid=3 Limit 2
Union all
Select * from table where movieidid=4 Limit 2
Temporary table #tempmovie table will contain data like this
+------------+---------+
| MovieId | rating |
+------------+---------+
| 1 | 4 |
| 1 | 3 |
| 2 | 3 |
| 2 | 4 |
| 3 | 1 |
| 3 | 2 |
| 4 | 4 |
| 4 | 2 |
+------------+---------+
then apply group by
Select movieId, AVG(rating)
from #tempMovie
Group by movieId
Drop table #tempmovie