Here are the my tables;
TableP:
Pname | Psize
x | -
y | -
z | -
g | -
h | -
TableS:
Pname | Pdate | Ptext
x | XX.XX.XXXX | aasdhb
x | XX.XX.XXXX | asdbahsbdhasbdh
y | XX.XX.XXXX | ajsdbajsdba
y | XX.XX.XXXX | asndansjdbasd
x | XX.XX.XXXX | asd
z | XX.XX.XXXX | asdasbdhasb
g | XX.XX.XXXX | asdnjasdja
g | XX.XX.XXXX | asndjsabdas
h | XX.XX.XXXX | asndjand
x | XX.XX.XXXX | asdjasndnaksd
As you can notice, i've added a new column (Psize) which stands for storing TableS.Ptext length.
How can i update Psize with related Ptext length?
Here is the my query which is not work :) (Subquery returns more than 1 row)
UPDATE TableP
set TableP.Psize = (SELECT sum(LENGTH(Ptext)) as length
FROM TableS group by Pname)
where TableP.Pname = TableS.Pname
Thanks in advance.
Try:
UPDATE TableP p
inner join (
SELECT Pname, sum(LENGTH(Ptext)) as length
FROM TableS
group by Pname
) s on p.Pname = s.Pname
set p.Psize = s.length
Another form keeping your subselect:
UPDATE TableP p
set p.Psize = (
SELECT sum(LENGTH(s.Ptext))
FROM TableS s
where s.pname = p.pname
)
where exists ( -- just to keep it consistent
select 1
from tables s
where s.pname = p.pname
);
Related
I am trying to get the sum of multiple rows from 2 different tables, but somehow the result returns multiple rows.
I need to get the SUM of quotation_item_amount (group by quotation_id) and invoice_item_amount (group by invoice_id) and if I query unpaid quotation, I need to get WHERE SUM(invoice) < SUM(quotation)
So here's my sample table
table client_project_id
+-------------------+-----------+----------------------+
| client_project_id | client_id | client_project_title |
+-------------------+-----------+----------------------+
| 23 | 5 | Project 1 |
| 17 | 9 | Project 2 |
| 54 | 7 | Project 3 |
+-------------------+-----------+----------------------+
table quotation
+--------------+-------------------+------------------+
| quotation_id | client_project_id | quotation_number |
+--------------+-------------------+------------------+
| 1 | 23 | Q/01/2020/001 |
| 2 | 17 | Q/01/2020/002 |
| 3 | 54 | Q/01/2020/003 |
+--------------+-------------------+------------------+
table quotation_item
+-------------------+--------------+-----------------------+
| quotation_item_id | quotation_id | quotation_item_amount |
+-------------------+--------------+-----------------------+
| 1 | 1 | 500 |
| 2 | 1 | 700 |
| 3 | 1 | 600 |
| 4 | 2 | 200 |
| 5 | 2 | 150 |
| 6 | 3 | 900 |
+-------------------+--------------+-----------------------+
table invoice
+--------------+-------------------+------------------+
| invoice_id | client_project_id | invoice_number |
+--------------+-------------------+------------------+
| 1 | 23 | I/01/2020/001 |
| 2 | 17 | I/01/2020/002 |
| 3 | 54 | I/01/2020/003 |
+--------------+-------------------+------------------+
table invoice_item
+-------------------+--------------+-----------------------+
| invoice_item_id | invoice_id | invoice_item_amount |
+-------------------+--------------+-----------------------+
| 1 | 1 | 500 |
| 2 | 1 | 700 |
| 3 | 1 | 600 |
| 4 | 2 | 200 |
| 5 | 2 | 150 |
| 6 | 3 | 900 |
+-------------------+--------------+-----------------------+
The result that I need to obtain is:
SUM of quotation_item_amount and SUM of invoice_item_amount PER client_project_id
To query WHERE SUM(invoice) < SUM(quotation)
Here is my latest try at the query
SELECT
SUM(quotation_item.quotation_item_amount) as quot_amt,
SUM(invoice_item.invoice_item_amount) as inv_amt,
data_client_project.client_project_id,
data_client.client_name
FROM data_client_project a
LEFT JOIN quotation b ON a.client_project_id = b.client_project_id
LEFT JOIN data_client d ON a.client_id = d.client_id
LEFT JOIN invoice i ON a.client_project_id = i.client_project_id
JOIN (
SELECT quotation_id,
SUM(c.quotation_item_amount) as quot_amt
FROM quotation_item c
GROUP BY c.quotation_id
) quotitem
ON b.quotation_id = quotitem.quotation_id
JOIN (
SELECT invoice_id,
SUM(e.invoice_item_price) as inv_amt
FROM invoice_item e
GROUP BY e.invoice_id
) invitem
ON i.invoice_id = invitem.invoice_id
However, this results in multiple duplicate rows of the quotation_item_amount and invoice_item_amount.
Have tried using UNION / UNION ALL and several other queries which just do not work.
Thank you for all your suggestions.
It looks like you are trying to aggregate along two different dimensions at the same time. The solution is to pre-aggregate along each dimension:
SELECT *
FROM data_client_project cp LEFT JOIN
(SELECT q.client_project_id,
SUM(qi.quotation_item_amount * qi.quotation_item_qty) as quot_amt
FROM quotation q JOIN
quotation_item qi
ON qi.quotation_id = q.quotation_id
GROUP BY q.client_project_id
) q
USING (client_project_id) LEFT JOIN
(SELECT i.client_project_id,
SUM(invoice_item_price) as inv_amt
FROM invoice i JOIN
invoice_item ii
ON i.invoice_id = ii.invoice_id
GROUP BY i.client_project_id
) i
USING (client_project_id);
Two notes about your style.
First, you are using arbitrary letters for table aliases. This makes the query quite hard to follow and becomes quite awkward if you add new tables, remove tables, or rearrange the names. Use abbreviations for the tables. Much easier to follow.
Second, I don't really recommend SELECT * for such queries. But, you can avoid duplicated column by replacing ON with USING.
I may be missing something, but your table descriptions do not include a example for data_client or data_client_project Given your example, I expect your row expansion is coming from the first 3 joins.
Make sure that the below is giving you the list of data you want first, then try joining in the calculation:
SELECT *
FROM data_client_project a
LEFT JOIN quotation b ON a.client_project_id = b.client_project_id
LEFT JOIN data_client d ON a.client_id = d.client_id
LEFT JOIN invoice i ON a.client_project_id = i.client_project_id;
#you may want to append the above with a limit 100 for testing.
if you have duplicated rows form the main query then add distinct for obatin a only distinct rows
and andd the where conditio for filtering the result by quotitem.quot_amt < invitem.inv_amt
SELECT distinct a.*, b.*, d.*, i.*
FROM data_client_project a
LEFT JOIN quotation b ON a.client_project_id = b.client_project_id
LEFT JOIN data_client d ON a.client_id = d.client_id
LEFT JOIN invoice i ON a.client_project_id = i.client_project_id
JOIN (
SELECT quotation_id,
SUM(c.quotation_item_amount * c.quotation_item_qty) as quot_amt
FROM quotation_item c
GROUP BY c.quotation_id
) quotitem ON b.quotation_id = quotitem.quotation_id
JOIN (
SELECT invoice_id,
SUM(e.invoice_item_price) as inv_amt
FROM invoice_item e
GROUP BY e.invoice_id
) invitem ON i.invoice_id = invitem.invoice_id
WHERE quotitem.quot_amt < invitem.inv_amt
Hi im looking for an MySQL Select that returns only that rows with doubled entries in column xxx
example:
+------+------+------------+--------------------+
| id | name | work_date | daily_typing_pages |
+------+------+------------+--------------------+
| 1 | John | 2007-01-24 | 250 |
| 2 | Ram | 2007-05-27 | 220 |
| 3 | Jack | 2007-05-06 | 170 |
| 4 | Jack | 2007-04-06 | 100 |
| 5 | Jill | 2007-04-06 | 220 |
| 6 | Zara | 2007-06-06 | 300 |
| 7 | Zara | 2007-02-06 | 350 |
+------+------+------------+--------------------+
Got This Table and i want to read out all entries thats name is listed more than once,
my Query is not working cause it just shows entries with two times the name just once
SELECT id, name, COUNT(name) AS count
FROM table_xy
having count(name) > 1;
what i want to have returned:
+------+------+------------+
| id | name | count |
+------+------+------------+
| 3 | Jack | 2 |
| 4 | Jack | 2 |
| 6 | Zara | 2 |
| 7 | Zara | 2 |
+------+------+------------+
Is there a way to get that?
You could use a subquery for your group by:
SELECT x.id, y.name, y.count
FROM table_xy AS x
INNER JOIN
( SELECT Name, COUNT(*) AS count
FROM table_xy
GROUP BY Name
HAVING COUNT(*) > 1
) AS y
ON y.Name = x.Name;
Alternatively you could use a self join with distinct if you don't need the count:
SELECT DISTINCT x.ID, x.Name
FROM table_xy AS x
INNER JOIN table_xy AS y
ON x.Name = y.Name
AND x.ID != y.ID;
Or a self join with GROUP BY if you do need the count:
SELECT x.ID, x.Name, COUNT(y.ID) + 1 AS count
FROM table_xy AS x
INNER JOIN table_xy AS y
ON x.Name = y.Name
AND x.ID != y.ID
GROUP BY x.ID, x.Name;
Examples on SQL Fiddle
try this...
SELECT x.ID, x.Name, COUNT(y.ID) + 1 AS count
FROM table_xy AS x
INNER JOIN table_xy AS y
ON x.Name = y.Name
AND x.ID != y.ID
GROUP BY x.ID, x.Name;
I'm a bit stuck with a php/Mysql Query. I got 2 tables :
table_users table_ranks
---------------- ------------------------
| id | points | | name | points_needed |
---------------- ------------------------
| 1 | 2 | | lvl0 | 0 |
| 2 | 10 | | lvl1 | 10 |
| 3 | 21 | | lvl2 | 20 |
| 4 | 29 | | lvl3 | 30 |
---------------- ------------------------
I need an ouput like this :
User_1 = lvl0 (because user has 2 points)
User_2 = lvl1 (because user has just reached 10 points)
...
User_4 = lvl2 (because user has not yet reached 30 points)
Think you :)
Regards.
You can do it like this
SELECT
tu.id,
tr.name,
tu.points
FROM table_ranks as tr
LEFT JOIN (SELECT * FROM table_ranks LIMIT 1,69596585953484) as l
ON l.points_needed = (SELECT MIN(points_needed) FROM table_ranks WHERE points_needed > tr.points_needed limit 1)
LEFT OUTER JOIN table_users AS tu ON tu.points >= tr.points_needed AND tu.points < l.points_needed
WHERE tu.id IS NOT NULL
group by tu.id
Fiddle
Output
-------------------------
| id | points | name |
-------------------------
| 1 | lvl0 | 2 |
| 2 | lvl1 | 10 |
| 3 | lvl2 | 21 |
| 4 | lvl2 | 29 |
-------------------------
give this a try, a little bit messy due to table design,
SELECT u.*, r.name
FROM table_users u
INNER JOIN
(
SELECT x.name,
x.points_needed start_point,
COALESCE(y.points_needed - 1, 2000000) end_point
FROM
(
SELECT name, points_needed, #rank:=#rank+1 ranks
FROM table_ranks a, (SELECT #rank:=0) b
ORDER BY points_needed
) x
LEFT JOIN
(
SELECT name, points_needed, #rank1:=#rank1+1 ranks
FROM table_ranks a, (SELECT #rank1:=0) b
ORDER BY points_needed
) y ON x.ranks+1 = y.ranks
) r ON u.points BETWEEN r.start_point AND r.end_point
SQLFiddle Demo
I have to generate a report using 4 tables, I tried a lot of joins, but I get wrong values :(
Hope someone will help me.
StaffAssign Table:
----------------------------
| Tid | StaffId | Planned |
----------------------------
| 123 | 2 | 10:00:00 |
| 123 | 4 | 05:00:00 |
| 124 | 2 | 09:00:00 |
----------------------------
ActualEffort Table:
--------------------------------------------
| Tid | StaffId | ActualEffort | logdate |
--------------------------------------------
| 123 | 2 | 05:00:00 |2012-09-01|
| 123 | 4 | 05:00:00 |2012-09-01|
| 123 | 2 | 06:00:00 |2012-09-03|
| 124 | 2 | 09:00:00 |2012-09-04|
--------------------------------------------
ProjectList Table:
-------------------
| ProjectId | Tid |
-------------------
| 1 | 123 |
| 2 | 124 |
-------------------
ProjectName Table:
-------------------
| Id | name |
-------------------
| 1 | project1 |
| 2 | project2 |
-------------------
Below is the Query I'm using:
SELECT P.id AS projectid,P.name,
SEC_TO_TIME(SUM(TIME_TO_SEC(A.planned)))planned,SEC_TO_TIME(SUM(TIME_TO_SEC(E.actualeffort)))actual FROM actualeffort E
INNER JOIN staffassign A ON A.tid = E.tid
INNER JOIN projectlist L ON L.tid = A.tid
INNER JOIN projectname P ON P.id = L.projectid
WHERE E.logdate BETWEEN FROM_UNIXTIME('1346475600') AND FROM_UNIXTIME('1348290000')
GROUP BY P.id
I'm getting this:
---------------------------------------------
| projectid | name | planned | actual |
---------------------------------------------
| 1 | project1 | 15:00:00| 12:00:00 |
| 2 | project2 | 09:00:00| 09:00:00 |
---------------------------------------------
But it should be like:
---------------------------------------------
| projectid | name | planned | actual |
---------------------------------------------
| 1 | project1 | 15:00:00| 16:00:00 |
| 2 | project2 | 09:00:00| 09:00:00 |
---------------------------------------------
I'm very confused that, I don't know where I'm going wrong with the joins.
Someone please help me, I'm struck with this.
The WHERE filter may be wrong. Note that first datetime in the condition starts at '08:00:00' -
SELECT FROM_UNIXTIME('1346475600') dt1, FROM_UNIXTIME('1348290000') dt2;
+---------------------+---------------------+
| dt1 | dt2 |
+---------------------+---------------------+
| 2012-09-01 08:00:00 | 2012-09-22 08:00:00 |
+---------------------+---------------------+
The type of ActualEffort.logdate field is DATE; the value '2012-09-01' is less then '2012-09-01 08:00:00'. So change this condition or use DATE function -
WHERE
E.logdate BETWEEN
DATE(FROM_UNIXTIME('1346475600')) AND DATE(FROM_UNIXTIME('1348290000'))
(edited)
For one thing, when you join StaffAssign and ActualEffort on the Tid column only, you get a mini-Cartesian product for Tid=123 in particular, because both tables contain more than one row with that Tid and there's no other specific condition to establish a 1:1 or, at most, 1:N relationship between the rows.
But in fact, 1:N wouldn't do either: although it wouldn't give you the Cartesian product effect, it would result in duplicated values on one side and, as a consequence, in a distorted SUM.
Therefore, data in StaffAssign and those in ActualEffort must be aggregated separately, then joined, something like this:
SELECT
pl.ProjectId,
pn.name,
sa.Planned,
ae.ActualEffort
FROM ProjectList pl
JOIN ProjectName pn
ON pn.Id = pl.ProjectId
LEFT JOIN (SELECT Tid, SEC_TO_TIME(SUM(TIME_TO_SEC(Planned))) Planned FROM StaffAssign GROUP BY Tid) sa
ON sa.Tid = pl.Tid
LEFT JOIN (SELECT Tid, SEC_TO_TIME(SUM(TIME_TO_SEC(ActualEffort))) ActualEffort FROM ActualEffort GROUP BY Tid) ae
ON ae.Tid = pl.Tid
GROUP BY ProjectId;
There is an error in your SQL:
You wan't to join p.ProjectID not p.id
Try this query
SELECT P.id AS projectid,P.name,
SEC_TO_TIME(SUM(TIME_TO_SEC(A.planned)))planned,SEC_TO_TIME(SUM(TIME_TO_SEC(E.actualeffort)))actual FROM actualeffort E
INNER JOIN staffassign A ON A.tid = E.tid
INNER JOIN projectlist L ON L.tid = A.tid
INNER JOIN projectlist L ON L.tid = E.tid // you have not added this line
INNER JOIN projectname P ON P.id = L.projectid
WHERE E.logdate BETWEEN FROM_UNIXTIME('1346475600') AND FROM_UNIXTIME('1348290000')
GROUP BY P.id
a join between L and E should be present.
I need to filter only these table rows which have same values in x and y columns.
_______________________________________
|
| x | y | name |
________________________________________
|
| 1 | 2 | A |
|______________________________________
| 2 | 1 | B |
|______________________________________
| 1 | 2 | C |
|_______________________________________
The final result should be that I have A and C result. I need to filter these rows which has identical x and y values.
_______________________________________
|
| x | y | name |
________________________________________
|
| 1 | 2 | A |
|______________________________________
______________________________________
| 1 | 2 | C |
|_______________________________________
I' ve tried this code but I only managed to with one field.
select *
from auto
where x in (
select x
from auto
group by x
having count(*) > 1
);
SELECT t1.*
FROM tablename t1, tablename t2
WHERE t1.x = t2.x
AND t1.y = t2.y
AND t1.primary_key != t2.primary_key
select * from
auto a, ( SELECT x, y, COUNT(*) FROM auto GROUP BY x, y HAVING COUNT(*) > 1 ) b
where a.x = b.x
and a.y = b.y
will mark your other question as duplicate