Unique records query - unique

The following query is showing same user for multiple times, how to make it unique?
$query = 'SELECT a.connection_id, a.connect_from, a.connect_to,
b.userid, b.thumb, c.name, d.user_id, d.field_id,
d.value as bday, e.creator, e.id as videoprofile,
DATE_FORMAT(FROM_DAYS(DATEDIFF(NOW(),d.value)), "%Y")+0 AS age
FROM `#__community_connection` AS a
LEFT JOIN `#__community_users` AS b
ON a.connect_to = b.userid
LEFT JOIN `#__users` AS c ON a.connect_to = c.id
LEFT JOIN `#__community_fields_values` AS d
ON a.connect_to = d.user_id
LEFT JOIN `#__community_videos` AS e ON a.connect_to = e.creator
WHERE a.connect_from = "' . $uid .'" AND d.field_id = "3"
ORDER BY DAYOFMONTH( bday ) ASC';

Add DISTINCT after your SELECT to return only unique rows. So change the first line of your code to the following:
$query = 'SELECT DISTINCT a.connection_id, a.connect_from, a.connect_to, ...
[The rest of your query follows here.]

Not entirely sure what you're asking but I assume you want a unique identifacation method for your users?
Well in PHP you can hash their ip address and use that as their id, however it contains numbers and letters, so that'll make it unique i suppose :)
Here's how it'll look
.md5($data['post_ip']);
it'll appear different to everyone, for example, mine appears as the following
e36e263f082188a317f89e0dfef766ed
hopefully this is what you're looking for :)

Related

MySQL SUM function not working for multiple rows order by categori Id

I want to list total vote poor,fair,good,vgood,excellent,yes,no from my survey_result table but the query only one time loop.
This is survey_result table.
And this is query result
SELECT
categori.s_categori_id,
categori.categori_name_en,
categori.categori_name_ar,
categori.categori_type,
question.survey_id,
question.question_en,
question.question_ar,
SUM(result.poor) AS poor,
SUM(result.fair ) AS fair,
SUM(result.good) AS good,
SUM(result.vgood) AS vgood,
SUM(result.excellent) AS excellent,
SUM(result.yes) AS yes,
SUM(result.no) As no,
result.comment
FROM
survey_categori AS categori
INNER JOIN survey_questions AS question ON categori.s_categori_id =
question.s_categori_id
INNER JOIN survey_result AS result ON result.s_question_id =
question.survey_id
WHERE
categori.survey_type = 'class'
GROUP BY
question.survey_id
you have to add group by below fields that i added in your query
categori.s_categori_id,
categori.categori_name_en,
categori.categori_name_ar,
categori.categori_type,
question.survey_id,
question.question_en,
question.question_ar,
SUM(result.poor) AS poor,
SUM(result.fair ) AS fair,
SUM(result.good) AS good,
SUM(result.vgood) AS vgood,
SUM(result.excellent) AS excellent,
SUM(result.yes) AS yes,
SUM(result.no) As no,
result.comment
FROM
survey_categori AS categori
INNER JOIN survey_questions AS question ON categori.s_categori_id =
question.s_categori_id
INNER JOIN survey_result AS result ON result.s_question_id =
question.survey_id
WHERE
categori.survey_type = 'class'
GROUP BY
question.survey_id,categori.categori_name_en,
categori.categori_name_ar,
categori.categori_type,
question.question_en,
question.question_ar
I want to list total vote poor,fair,good,vgood,excellent,yes,no from my survey_result table
This sounds like you want the total across the entire survey. If so, you shouldn't use GROUP BY. To get one row:
SELECT SUM(result.poor) AS poor,
SUM(sr.fair ) AS fair,
SUM(sr.good) AS good,
SUM(sr.vgood) AS vgood,
SUM(sr.excellent) AS excellent,
SUM(sr.yes) AS yes,
SUM(sr.no) As no
FROM survey_categori sc INNER JOIN
survey_questions sq
ON sc.s_categori_id = sq.s_categori_id INNER JOIN
survey_result sr
ON sr.s_question_id = sq.survey_id
WHERE c.survey_type = 'class';
You would use GROUP BY if you wanted multiple rows in the result set. Then, every column (or expression) in the GROUP BY would (normally) be added to the SELECT. For instance, if you wanted one row per survey, you would have:
SELECT sq.survey_id,
SUM(. . .)
. . .
FROM . . .
GROUP BY sq.survey_id

How to make query

review table has store_idx, user_idx etc...
I want to create a query sentence that gets information about the store to which the user has bookmarked with the user_id value entered.
The query sentence I made is
select A.store_name
, A.store_img
, count(B.store_idx) as review_cnt
from board.store A
Left
Join board.review B
On A.store_idx is B.store_idx
where store_idx is (select A.store_idx from bookmark where user_id = ?)
However, nothing came out as a result.
Help me..
Please use below Query:
SELECT store_name
, store_img
, SUM(review_cnt) AS review_cnt
FROM
( SELECT DISTINCT A.store_name
, A.store_img
, CASE WHEN B.store_idx IS NULL THEN 0 ELSE 1 END AS review_cnt
FROM bookmark br
JOIN board.store A
ON A.store_idx = br.store_idx
LEFT
JOIN board.review B
ON A.store_idx = B.store_idx
WHERE br.user_id = ?
)T
The WHERE clause is obviously filtering out all rows. We can't do much about that. But your query is also lacking a GROUP BY, the table aliases can be improved, and the join condition is not correct.
So, try this version:
select s.store_name, s.store_img, count(b.store_idx) as review_cnt
from board.store s left join
board.review r
on s.store_idx = r.store_idx
where b.store_idx in (select b.store_idx
from bookmark b
where b.user_id = ?
);

SQL just do the opposite of this

SELECT Name FROM Anime LEFT JOIN anime_user2 ON anime_idAnime = idAnime WHERE users_userID = $userID
I want to get the exact opposite of this but it's not working with
WHERE users_userID != $userID
I get 4 Names, but I want every Name except those 4 Names.
Do you how to do this?
You can use NOT IN operator like this:
SELECT NAME
FROM ANIME a
WHERE a.NAME NOT IN (
SELECT Name
FROM Anime LEFT JOIN anime_user2 ON anime_idAnime = idAnime
WHERE users_userID = $userID
)
BEWARE: Depending on what is your table histogram, this query might be too slow to use it on a web page or application.

MySQL: how can I count number of articles by a join table

I have a table with news items, I have another table with media_types, I want to make one simple query that reads the media_types table and count for each record how many news_items exist.
The result will be turned into a json response that I will use for a chart, this is my SQLstatement
SELECT
gc.country AS "country"
, COUNT(*) AS "online"
FROM default_news_items AS ni
JOIN default_news_item_country AS nic ON (nic.id = ni.country)
JOIN default_country AS c ON (nic.country = c.id)
JOIN default_geo_country AS gc ON (gc.id = c.geo_country)
LEFT JOIN default_medias ON (m.id = ni.media)
WHERE TRUE
AND ni.deleted = 0
AND ni.date_item > '2013-10-23'
AND ni.date_item < '2013-10-29'
AND gc.country <> 'unknown'
AND m.media_type = '14'
GROUP BY gc.country
ORDER BY `online` desc LIMIT 10
This is the json respond I create from the mysql respond
[
{"country":"New Zealand","online":"7"},
{"country":"Switzerland","online":"1"}
]
How do I add print and social data to my output like this
I would like the json respond look like this
[
{"country":"New Zealand","online":"7", "social":"17", "print":"2"},
{"country":"Switzerland","online":"1", "social":"7", "print":"1"}
]
Can I use the count (*) in the select statement to do something like this
COUNT( * ) as online, COUNT( * ) as social, COUNT( * ) as print
Is it possible or do I have to do several SQL statement to get the data I'm looking for?
This is the general structure:
SELECT default_geo_country.country as country,
SUM(default_medias.media_type = 14) as online,
SUM(default_medias.media_type = XX) as social,
SUM(default_medias.media_type = YY) as print
FROM ...
JOIN ...
WHERE ...
GROUP BY country
I think you want conditional aggregation. Your question, however, only shows the online media type.
Your query would be more readable by using table aliases and removing the back quotes. Also, if media_type is an integer, then you should not enclose the constant for comparison in single quotes -- I, for one, find it misleading to compare a string constant to an integer column.
I suspect this is the way you want to go. Where the . . . is, you want to fill in with the counts for the other media types.
SELECT default_geo_country.country as country,
sum(media_type = '14') as online,
sum(default_medias.media_type = XX) as social,
sum(default_medias.media_type = YY) as print
. . .
FROM default_news_items ni JOIN
default_news_item_country nic
ON nic.id = ni.country JOIN
default_country dc
ON nic.country = dc.id JOIN
default_geo_country gc
ON gc.id = dc.geo_country LEFT JOIN
default_medias dm
ON dm.id = dni.media
WHERE ni.deleted = '0'
AND ni.date_item > '2013-10-23'
AND ni.date_item < '2013-10-29'
AND gc.country <> 'unknown'
GROUP BY gc.country
ORDER BY online desc
LIMIT 10

SQL: Get latest entries from history table

I have 3 tables
person (id, name)
area (id, number)
history (id, person_id, area_id, type, datetime)
In this tables I store the info which person had which area at a specific time. It is like a salesman travels in an area for a while and then he gets another area. He can also have multiple areas at a time.
history type = 'I' for CheckIn or 'O' for Checkout.
Example:
id person_id area_id type datetime
1 2 5 'O' '2011-12-01'
2 2 5 'I' '2011-12-31'
A person started traveling in area 5 at 2011-12-01 and gave it back on 2011-12-31.
Now I want to have a list of all the areas all persons have right now.
person1.name, area1.number, area2.number, area6.name
person2.name, area5.number, area9.number
....
The output could be like this too (it doesn't matter):
person1.name, area1.number
person1.name, area2.number
person1.name, area6.number
person2.name, area5.number
....
How can I do that?
This question is, indeed, quite tricky. You need a list of the entries in history where, for a given user and area, there is an 'O' record with no subsequent 'I' record. Working with just the history table, that translates to:
SELECT ho.person_id, ho.area_id, ho.type, MAX(ho.datetime)
FROM History AS ho
WHERE ho.type = 'O'
AND NOT EXISTS(SELECT *
FROM History AS hi
WHERE hi.person_id = ho.person_id
AND hi.area_id = ho.area_id
AND hi.type = 'I'
AND hi.datetime > ho.datetime
)
GROUP BY ho.person_id, ho.area_id, ho.type;
Then, since you're really only after the person's name and the area's number (though why the area number can't be the same as its ID I am not sure), you need to adapt slightly, joining with the extra two tables:
SELECT p.name, a.number
FROM History AS ho
JOIN Person AS p ON ho.person_id = p.id
JOIN Area AS a ON ho.area_id = a.id
WHERE ho.type = 'O'
AND NOT EXISTS(SELECT *
FROM History AS hi
WHERE hi.person_id = ho.person_id
AND hi.area_id = ho.area_id
AND hi.type = 'I'
AND hi.datetime > ho.datetime
);
The NOT EXISTS clause is a correlated sub-query; that tends to be inefficient. You might be able to recast it as a LEFT OUTER JOIN with appropriate join and filter conditions:
SELECT p.name, a.number
FROM History AS ho
JOIN Person AS p ON ho.person_id = p.id
JOIN Area AS a ON ho.area_id = a.id
LEFT OUTER JOIN History AS hi
ON hi.person_id = ho.person_id
AND hi.area_id = ho.area_id
AND hi.type = 'I'
AND hi.datetime > ho.datetime
WHERE ho.type = 'O'
AND hi.person_id IS NULL;
All SQL unverified.
You're looking for results where each row may have a different number of columns? I think you may want to look into GROUP_CONCAT()
SELECT p.`id`, GROUP_CONCAT(a.`number`, ',') AS `areas` FROM `person` a LEFT JOIN `history` h ON h.`person_id` = p.`id` LEFT JOIN `area` a ON a.`id` = h.`area_id`
I haven't tested this query, but I have used group concat in similar ways before. Naturally, you will want to tailor this to fit your needs. Of course, group concat will return a string so it will require post processing to use the data.
EDIT I thikn your question has been edited since I began responding. My query does not really fit your request anymore...
Try this:
select *
from person p
inner join history h on h.person_id = p.id
left outer join history h2 on h2.person_id = p.id and h2.area_id = h.area_id and h2.type = 'O'
inner join areas on a.id = h.area_id
where h2.person_id is null and h.type = 'I'