Simple way to calculate average by union of three table in MySQL - php

I have a union of three tables (t1,t2,t3). Each return exactly the same number of records, first column is id, second amount:
1 10
2 20
3 20
1 30
2 30
3 10
1 20
2 40
3 60
Is there a simple in SQL way to calculate the average up to only get:
1 20
2 30
3 30
can the new value store in an another table t4 with php code?

One way to get an average is to use the SQL AVG() aggregate function.
If we want an average "per id", then we need to include a GROUP BY clause.
We can use an inline view query in place of a table reference. (MySQL refers to this as a derived table.
Here's an example of what the query might look like:
SELECT t.id
, AVG(t.amount) AS avg_amount
FROM ( SELECT t1.id
, t1.amount
FROM t1
UNION ALL
SELECT t2.id
, t2.amount
FROM t2
UNION ALL
SELECT t3.id
, t3.amount
FROM t3
) t
GROUP BY t.id
ORDER BY t.id

Related

How do I get count of a row in SQL

I am a beginner regarding SQL queries so I hope that someone can help me with this.
I have a table that has 2 columns that are called MID and jachtID.
What I need is the count of how many of the same jachtIDS there are with different MIDS attached to them like this:
MID jachtID
89 10
95 10
83 11
The result should look something like this:
MID jachtID count
89 10 2
95 10 2
83 11 1
And I need this for all of the rows
I have tried using
SELECT count(DISTINCT jachtID) FROM table
But this just gives me 1 big number and not the result that I need.
Any help would be appreciated.
You can try the following query:
SELECT
T.MID,
T.jachtID,
jT.total
FROM table T INNER JOIN
(
SELECT
jachtID,
COUNT(*) total
FROM table
GROUP BY jachtID
)AS jT
ON T.jachtID = jT.jachtID
First get count of each jachtID by the following query:
SELECT
jachtID,
COUNT(*) total
FROM table
GROUP BY jachtID
Then make an INNER JOIN between the main table and the above query and get the corresponding jatchtID count thereby.
You might be able to do this with some GROUP BY magic, but I'm not sure, since you want all the rows. Using a sub query will work, though.
SELECT
a.MID,
a.jachtID,
(SELECT count(b.jachtID) FROM table AS b WHERE b.jachtID= a.jachtID) AS `count`
FROM table AS a

MySQL JOIN ratings by ID to details by ID

hoping someone can help. MySQL JOIN statements have never been my strong point and they just hurt my brain trying to figure them out.
I have table which stores ratings of an item in another table, tracked by ID.
What I need to do now though is display a list of items ordered by the ratings, high to low and low to high.
I can get a list of ratings per item, grouped by ID from the ratings table easily enough, but it's getting it JOINed to the items I get stuck on. Not all items have ratings either (yet), and so it would also be beneficial if the combined list didn't just stop at the end of the ratings that do exist.
OK, so here's my grouping statement:
SELECT `themeID` , SUM( `rating` ) AS ratings
FROM `votes`
GROUP BY `themeID`
ORDER BY `ratings` DESC
outputs
themeID ratings
1 6
3 3
2 2
6 2
Then the details table consists of various info, such as id, filename, name, date etc
Between the two tables, themeID and id are the same which links them. I've looked at some of the other answers to similar queries on SO, but I couldn't get any of the answers to work with my tables/queries (probably because I don't fully grasp JOIN's)
ANy help would be saving me a massive headache!
Just join the two tables and add the aggregation function.
SELECT d.id, d.filename, d.name, IFNULL(SUM(v.rating), 0) AS ratings
FROM details AS d
LEFT JOIN votes AS v ON d.id = v.themeID
GROUP BY d.id
I used LEFT JOIN so this will show the details even if there are no votes.
I have tested in sql server same u can get in Mysql
DROP TABLE #Item
create table #Item (ID int identity(1,1),ItemNAme varchar(10))
INSERT INTO #Item(ItemNAme)
SELECT 'A'
UNION ALL
SELECT 'B'
UNION ALL
SELECT 'C'
DROP TABLE #ItemRating
create table #ItemRating (ItemID int ,rating int)
INSERT INTO #ItemRating(ItemID,rating)
SELECT 3,2
UNION ALL
SELECT 2,11
UNION ALL
SELECT 1, 3
UNION ALL
SELECT 2, 4
union all
SELECT 1,5
UNION ALL
SELECT 3,12
UNION ALL
SELECT 1, 4
UNION ALL
SELECT 2, 1
SELECT m.ItemNAme,SUM(I.rating) as Rating
FROM #Item m INNER JOIN #ItemRating I ON m.ID=I.ItemID
group by m.ItemNAme
ORDER BY SUM(I.rating) asc
--OR same thing can achive
SELECT ItemNAme, Rating
FROM (
SELECT m.ItemNAme,SUM(I.rating) as Rating
FROM #Item m INNER JOIN #ItemRating I ON m.ID=I.ItemID
group by m.ItemNAme
)P
ORDER BY Rating Desc

Mysql select query performance gets bad

I got a mysql query that selects all clicks for each hour of a day.
This query worked good till we have alot of click entries in our database. Now it needs sometimes several seconds (up to 9!) to request the datas...
The query is:
SELECT h.clickHour, COUNT(clicktime) AS c
FROM ( SELECT 0 AS clickHour
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
UNION ALL SELECT 10
UNION ALL SELECT 11
UNION ALL SELECT 12
UNION ALL SELECT 13
UNION ALL SELECT 14
UNION ALL SELECT 15
UNION ALL SELECT 16
UNION ALL SELECT 17
UNION ALL SELECT 18
UNION ALL SELECT 19
UNION ALL SELECT 20
UNION ALL SELECT 21
UNION ALL SELECT 22
UNION ALL SELECT 23 ) AS h
INNER JOIN links l ON l.user_id = 1
LEFT OUTER
JOIN clicks
ON EXTRACT(HOUR FROM clicks.clicktime) = h.clickHour
AND DATE(clicks.clicktime) = '2014-09-21'
AND clicks.link_id = l.id
GROUP
BY h.clickHour
I got these unions because i need clicks for each hour also empty hours...
Please help!
Ok so we are talking about 0 to several thousand rows for the table clicks. The click time is saved as a timestamp and every click got a unique id. I see that the union thing is bad and i have to change it.
What i try now is to select all clicks of a day grouped by HOUR(clicktime):
But when i do so I get too many results like 10x then it should be.
I'd rewrite the query like this:
SELECT h.clickHour
, IFNULL(d.clickCount,0) AS c
FROM ( SELECT 0 AS clickHour UNION ALL SELECT 1 UNION ALL SELECT 2
UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5
UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14
UNION ALL SELECT 15 UNION ALL SELECT 16 UNION ALL SELECT 17
UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL SELECT 20
UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23
) h
LEFT
JOIN ( SELECT EXTRACT(HOUR FROM c.clicktime) AS clickHour
, SUM(1) AS clickCount
FROM clicks c
JOIN links l
ON l.user_id = 1
AND l.id = c.link_id
WHERE c.clicktime >= '2014-09-21'
AND c.clicktime < '2014-09-21' + INTERVAL 1 DAY
GROUP BY EXTRACT(HOUR FROM c.clicktime)
) d
ON d.clickHour = h.clickHour
The approach here is to get the inline view query d to return a maximum of 24 rows. This cranks through the clicks table to get the counts. W're going to defer the join operation to the fixed set of 24 rows until after we have calculated the hourly counts. (The join to h is there only to get rows with zero counts returned, which would otherwise just be "missing" rows.)
You can test the performance of the inline view query d, and of the entire query, I suspect there won't be much difference. The cost of materializing the inline view h isn't that much (there's some overhead, but it's very likely that will use the Memory storage engine; it's small enough and it should be simple integer datatype.) And that join operation of 24 rows to 24 rows won't be that expensive, even without any indexes available.
I suspect that the majority of time will be in materializing the derived table d.
We're going to want an index with a leading column of clickDate, so that we can use a more efficient index range scan operation, to avoid evaluating expressions for every flipping row in the table.
I changed this predicate: DATE(clickTime) = '2014-09-21' into a predicates that reference the bare column, this enables MySQL to consider an efficient range scan operation on the clickTime column, (to quickly eliminate a boatload of rows from consideration), rather than requiring that MySQL evaluate a function on every flipping row in the table.
Some performance gain may be obtained by making covering indexes available on the clicks and links tables (so that the query can be satisfied from the indexes, without a need to visit pages in the underlying table.)
At a minimum on the clicks table:
ON clicks (clickTime, link_id)
If id is unique (or primary key) on the links table, this index may not give any performance benefit:
ON links (id, user_id)
If a covering index used, the EXPLAIN output should show "Using index".
I don't see a way around the "Using filesort" operation, not without adding a column to clicks table that stores the clickTime truncated to the hour. With a column like that, and an appropriate index, it's possible that we could get the GROUP BY operation optimized using the index, avoiding the "Using filesort" operation.
Have you indexed?
Clicks table: clicktime, link_id
Links table: id, user_id

How to count same string in an array

I have a little problem , I want to count same string in an array ,
for example
My table like this:
id | data
---------------------------
1 | #user1,#user2,#user3
2 | #user1,#user4
3 | #user1,#user5
4 | #user2,#user3
How can I count #user1,#user2,etc.. ?
You can use find_in_set to find data in comma separated field.
SELECT COUNT(*)
FROM some_table
WHERE FIND_IN_SET('#user2', data)
This will give you a count of the rows that contain this string.
Note that this does suggest a database design that is not normalised and as this function can't use indexes it is likely to perform badly compared to a properly normalised database (ie, split the strings off onto a different table, with one row per string per id).
EDIT - if you want a count of all the strings:-
SELECT sub1.aString, COUNT(*)
FROM
(
SELECT DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(data, ',', 1 + units.i + 10 * tens.i), ',', -1) AS aString
FROM some_table,
(SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units,
(SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
) sub1
INNER JOIN some_table
ON FIND_IN_SET(sub1.aString, data)
GROUP BY sub1.aString
This uses a couple of sub queries to generate 100 rows for each row in you main table, each with a combination of the numbers 0 to 9 twice. From the combination it can calculate a number between 0 and 99 (can easily be expanded to add another sub query to go from 0 to 999, or more). It then uses SUBSTRING_INDEX with the generated number to split out the possible strings in data for each row. This will generate a LOT of duplicates, partly as the strings will likely be on many rows and partly because the last string on each row will be put out many times (ie, if there are 10 string, the last one will be put out 91 times due to the way SUBSTRING_INDEX is used). DISTINCT is used to remove these duplicates.
The result is then joined against your table using FIND_IN_SET, and COUNT / GROUP BY used to get all the counts of all the strings.
You can try somthing like this:-
SELECT COUNT(data)
FROM your_table
WHERE data LIKE '%#user1%'

SQL QUERY----Retrieve all email

$q="SELECT DISTINCT
t1.un_email,t6.email
FROM
sisters_7sisters.tbl_unsubscribe as t1,
sisters_7sisters.tbl_uptade_list as t6";
I write a query like above I need to retrieve all the unique emails from the tables
But it gives me pair of some results which are not unique ..I tried to get the email only once
from these tables.
It would be better to use a join to join those two tables and select the distinct email
The distinct you are using, is only applied to each column of the result and not both at the same time.
It you are not joing them and you do not have any where clause. Then you might be fine with this solution (No duplicate emails):
SELECT
t1.un_email AS email
FROM
sisters_7sisters.tbl_unsubscribe as t1
UNION
SELECT
t6.email
FROM
sisters_7sisters.tbl_uptade_list as t6
Or you can use a UNION ALL. This will return the duplicates:
SELECT
t1.un_email AS email
FROM
sisters_7sisters.tbl_unsubscribe as t1
UNION
SELECT
t6.email
FROM
sisters_7sisters.tbl_uptade_list as t6
Ithink you have forgot Join ocndition
when you use
select * from table1,table2
it will create a cartisian product
if table1 as
1
2
3
and table2 has
4
5
6
as their data.
cartesian product will be
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
to remove this unnecesary fields
you have to Join

Categories