How to get distinct results using GORM - mysql

In Go, I write a query that gives me all data but I just want to data where products.id and clients.id are distinct.
What is the simile query I can write?
res := find.Model(&domain.Clients{}).
Select ("products.id product_id, products.name product_name,"+
" clients.id id, clients.name name, clients.logo, clients.address, "+
"clients.business_id, clients.num_of_employee, clients.email, clients.sns_link, clients.phone").
Joins("LEFT JOIN company_interests ON company_interests.client_id = clients.id").
Joins("LEFT JOIN products ON products.id = company_interests.product_id").
Where("products.id = ? ", productId).Find(&resp)

In Go when i write "Select Distinct" then rest query , it is not valid in go. So, i got an idea to write the query using "group by". In Go "group by" syntax can be used by "GROUP" syntax . So, finally bellow query works fine for me.
res := find.Model(&domain.Clients{}).
Select ("products.id product_id, products.name product_name,"+
" clients.id id, clients.name name, clients.logo, clients.address, "+
"clients.business_id, clients.num_of_employee, clients.email, clients.sns_link, clients.phone").
Joins("LEFT JOIN company_interests ON company_interests.client_id = clients.id").
Joins("LEFT JOIN products ON products.id = company_interests.product_id").
Where("products.id = ? ", productId).
Group("company_interests.client_id, company_interests.product_id" ).Find(&resp)

Related

Optimize Query Mysql to count data in each district

i have this query for calculate success total in each district. this query works but its take until 2min to output data, i have 15k rows in orders.
SELECT
nsf.id,
nsf.province,
nsf.city,
nsf.district,
nsf.shipping_fee,
IFNULL((SELECT COUNT(orders.id) FROM orders
JOIN users ON orders.customer_id = users.id
JOIN addresses ON addresses.user_id = users.id
JOIN subdistricts ON subdistricts.id = addresses.subdistrict_id
WHERE orders.status_tracking IN ("Completed","Successful Delivery")
AND subdistricts.ninja_fee_id = nsf.id
AND orders.transfer_to = "cod"),0) as success_total
from ninja_shipping_fees nsf
GROUP BY nsf.id
ORDER BY nsf.province;
the output should be like this
can you help me to improve the peformance? Thanks
Try performing the grouping/calculation in a joined "derived table" instead of a "correlated subquery"
SELECT
nsf.id
, nsf.province
, nsf.city
, nsf.district
, nsf.shipping_fee
, COALESCE( g.order_count, 0 ) AS success_total
FROM ninja_shipping_fees nsf
LEFT JOIN (
SELECT
subdistricts.ninja_fee_id
, COUNT( orders.id ) AS order_count
FROM orders
JOIN users ON orders.customer_id = users.id
JOIN addresses ON addresses.user_id = users.id
JOIN subdistricts ON subdistricts.id = addresses.subdistrict_id
WHERE orders.status_tracking IN ('Completed', 'Successful Delivery')
AND orders.transfer_to = 'cod'
GROUP BY subdistricts.ninja_fee_id
) AS g ON g.ninja_fee_id = nsf.id
ORDER BY nsf.province;
"Correlated subqueries" are often a source of poor performance.
Other notes, I prefer to use COALESCE() because it is ANSI standard and available in most SQL implementations now. Single quotes are more typically used to denote strings literals.

how to optimize the mysql Query

how to increase the performance of this mysql query
SELECT '' AS sharedid,
hubber_posts.userID AS postowner,
hubber_posts.*,
'' AS sharedby,
hubber_posts.userID AS userID,
hubber_posts.posted_date AS DATE,
'' AS sharebyusr,
'' AS sharebyusrimg,
Concat_ws(' ', firstname, lastname) AS fullname,
username AS postedBy,
hubber_user.image,
hubber_user.gender AS gender,
(SELECT accounttype
FROM hubber_user_security us
WHERE hubber_user.ID = us.userID
AND hubber_posts.userID = us.userID) AS accounttype,
'' AS sharebyusrtype
FROM hubber_posts
INNER JOIN hubber_user
ON hubber_posts.userID = hubber_user.ID
WHERE hubber_posts.status = 1
Your example code has a correlated subquery. MySQL performs poorly with those, as of late 2016.
Try converting it to a JOINed table.
SELECT all that stuff,
us.accounttype
FROM hubber_posts
JOIN hubber_user ON hubber_posts.userID = hubber_user.ID
LEFT JOIN hubber_user_security us ON hubber_user.ID = us.userID
WHERE hubber_posts.status = 1
I used LEFT JOIN. Without the LEFT, any rows without a matching entry in that table will be suppressed from the result set.
You query is essentially this:
SELECT . . .
(SELECT accounttype
FROM hubber_user_security us
WHERE u.ID = us.userID AND
p.userID = us.userID
) AS accounttype,
. . .
FROM hubber_posts p INNER JOIN
hubber_user u
ON p.userID = u.ID
WHERE p.status = 1 ;
For this query, the optimal indexes are:
hubber_posts(status, userId)
hubber_user(Id)
hubber_user_security(userId)
I would note that the subquery has an extra correlation condition that is not necessary -- the user ids are already equal. And, you run the risk of getting an error if there are multiple account types.
You may intend:
(SELECT GROUP_CONCAT(accounttype)
FROM hubber_user_security us
WHERE u.ID = us.userID
) as accounttypes,
My suggestion is to support a join where hubber_posts is the base table and the 2 other tables are joined using nested loops.
No need to index hubber_posts for the join.
hubber_user.ID should be a PK.
hubber_user_security.userID should be indexed (and defined as a FK references hubber_user.ID).
As for the WHERE clause - only if you have relatively few rows where hubber_posts.status = 1 then you should add an index on hubber_posts.status
P.s.
since the join contain the condition -
ON hubber_posts.userID = hubber_user.ID
There is no need to compare both hubber_posts.userID and hubber_user.ID to us.userID

duplicate result in group_concat

I have this data in my database(3,15,6,4,15), and I tried to show it on my table using group concat, the problem is i got duplicate results. (3,15,6,4,15,3,15,6,4,15,3,15,6,4,15).
I tried to use distinct but it eliminate also the other "15".
What is the best solution for that?
thanks!
this is my query
SELECT users.*, GROUP_CONCAT(written.score separator ' - ') as Wscore, student_subject.*,SUM(written.score) as total, SUM(written.item) as item FROM users JOIN written ON users.idnumber=written.idnumber JOIN student_subject ON users.idnumber=student_subject.idnumber WHERE student_subject.teacher='$login_session' AND written.section='$section' AND written.level='$level' AND written.year='$year' AND written.subject='$subject' AND users.gender='male' AND written.period='first' GROUP BY users.idnumber order by users.lname
You probably just want distinct in the group_concat():
SELECT u.*, GROUP_CONCAT(distinct w.score separator ' - ') as Wscore,
ss.*, SUM(w.score) as total, SUM(w.item) as item
FROM users u JOIN
written w
ON u.idnumber = w.idnumber JOIN
student_subject ss
ON u.idnumber = ss.idnumber
WHERE ss.teacher = '$login_session' AND w.section='$section' AND
w.level = '$level' AND w.year = '$year' AND w.subject = '$subject' AND
u.gender = 'male' AND w.period = 'first'
GROUP BY u.idnumber
order by u.lname;
Notice how table aliases make the query easier to write and to read.

How to seperate out group concat results

I am using Group concat in aggregate function in my project to display subcategories of a categories.
This is MYSQL query.
$sql_query = "SELECT TC.category_name, GROUP_CONCAT(TS.sub_category_name ORDER BY TS.sub_category_name) from table_categories as TC
INNER JOIN
table_subcategory_categories as TSC
ON
TSC.category_id = TC.category_id
INNER JOIN
table_subcategories as TS
ON
TS.sub_categories_id = TSC.subcategory_id
GROUP BY TC.category_id
order by TC.category_name";
The Problem is i need to process these subcategories as separate entities. But Because of Group concat they becomes a single entity.
What is the solution for this?
Is there any alternative of Group concat to achieve the same.
Current:
Body Wash <a>Bathing Soap|Shower Gel</a> delete
This delete makes no sense here.
Expecting:
Body Wash <a>Bathing Soap</a> delete
<a>Shower Gel</a> delete
So why not just remove the GROUP_CONCAT...?
$sql_query = "SELECT TC.category_name, TS.sub_category_name
from table_categories as TC
INNER JOIN
table_subcategory_categories as TSC
ON
TSC.category_id = TC.category_id
INNER JOIN
table_subcategories as TS
ON
TS.sub_categories_id = TSC.subcategory_id
order by TC.category_name, TS.sub_category_name";
Try removing the group by:
select TC.category_name, TS.sub_category_name
from table_categories TC INNER JOIN
table_subcategory_categories TSC
ON TSC.category_id = TC.category_id INNER JOIN
table_subcategories TS
ON TS.sub_categories_id = TSC.subcategory_id
order by TC.category_name, TS.sub_category_name;
You are going to get the values in multiple rows. You will also get category_name repeated in each row. That is how SQL result sets work. If you don't want the category repeated, then do something on the application side to get the results you want.

Problems ordering the results of a SQL query when I have ties

My tables look like this:
qotwQuestion1a
QuestionId [primarykey]
Question
MemberId
PostDate
qotwVote1a
QuestionId [primarykey]
MemberId [primarykey]
Vote1a
qotwMember
MemberId [primarykey]
Name
Password
emailId
The Sql query below sums the number of votes for each questionId (which has a postDate between the startofweek and endofweek date) and then displays it.
$result2 = mysql_query(" SELECT * FROM qotwMember, qotwQuestion1a
WHERE qotwMember.MemberId=qotwQuestion1a.MemberId
AND PostDate>='".$startofweek."' AND PostDate<='".$endofweek."'
ORDER BY qotwQuestion1a.QuestionId DESC ");
while($row2 = mysql_fetch_array($result2))
{ //echo("testing");
$result3= mysql_query ("SELECT SUM(Vote1a) AS total FROM qotwVote1a
WHERE QuestionId='".$row2['QuestionId']."'
ORDER BY total DESC ");
while($row3 = mysql_fetch_array($result3))
{
echo $row2['Question'] . " " .$row2['Name'] . " " .$row3['total'];
}
}
This query works fine, except for the "ORDER BY total DESC". The query gives the result, but does not orders the result by "total".
But my issue is to get the questionId which has the maximum number of votes. if there is a tie between a few questionIds, i would need all of those questions.
Can someone help me with this
Best
Zeeshan
Your code is structured in such a way that you will only get one result record back every time the query runs. The SQL ORDER BY clause does not apply to the PHP code calling it.
You'll need to restructure this so that the ORDER BY clause is actually doing something.
I would replace the whole thing with just one query:
$result3= mysql_query ("
SELECT qotwQuestion1a.Question, qotwMember.Name, SUM(qotwVote1a.Vote1a) AS total
FROM qotwMember
INNER JOIN qotwQuestion1a
ON qotwMember.MemberId = qotwQuestion1a.MemberId
INNER JOIN qotwVote1a
ON qotwVote1a.QuestionId = qotwQuestion1a.QuestionId
WHERE PostDate>='".$startofweek."'
AND PostDate<='".$endofweek."'
GROUP BY qotwQuestion1a.Question, qotwMember.Name
ORDER BY total DESC
");
while($row3 = mysql_fetch_array($result3)) {
echo $row3['Question'] . " " .$row3['Name'] . " " .$row3['total'];
}
This assumes that Question and Name are unique by ID. If not, you'll probably want to break this up into two queries, using the IDs instead of names to look up information:
SELECT qotwQuestion1a.QuestionId, SUM(qotwVote1a.Vote1a) AS total
FROM qotwQuestion1a
INNER JOIN qotwVote1a
ON qotwVote1a.QuestionId = qotwQuestion1a.QuestionId
WHERE PostDate>='".$startofweek."'
AND PostDate<='".$endofweek."'
GROUP BY qotwQuestion1a.QuestionId
ORDER BY total DESC
Then look up member name and question based on the QuestionId.
Or you could make a really, really big query:
SELECT qotwQuestion1a.Question, qotwMember.Name, SubQuery.total
FROM (
SELECT qotwQuestion1a.QuestionId, SUM(qotwVote1a.Vote1a) AS total
FROM qotwQuestion1a
INNER JOIN qotwVote1a
ON qotwVote1a.QuestionId = qotwQuestion1a.QuestionId
WHERE PostDate>='".$startofweek."'
AND PostDate<='".$endofweek."'
GROUP BY qotwQuestion1a.QuestionId
) SubQuery
INNER JOIN qotwQuestion1a
ON SubQuery.QuestionId = qotwQuestion1a.QuestionId
INNER JOIN qotwMember
ON qotwMember.MemberId = qotwQuestion1a.MemberId
ORDER BY total DESC
The problem is that the second query always returns single row. You should combine both queries using the GROUP statement, something like this:
SELECT qotwQuestion1a.QuestionId, SUM(Vote1a) AS total
FROM qotwMember, qotwQuestion1a, Vote1a
WHERE qotwMember.MemberId=qotwQuestion1a.MemberId
AND qotwQuestion1a.QuestionId=Vote1a.QuestionId
AND PostDate>='".$startofweek."' AND PostDate<='".$endofweek."'
GROUP BY qotwQuestion1a.QuestionId
ORDER BY total desc;