How to make CouchBase sub-query with RAW MAX , execution faster - couchbase

I have this query:
"SELECT meta(d).id as ID, meta(d).cas as CAS, d.* "
+"FROM (SELECT RAW MAX([t.eventTimestamp, META(t).id])[1] "
+"FROM `xyz` as t "
+"WHERE t.`docType` = '" +docType.toString() + "' "
+predicates
+"GROUP BY t.id "
+") as q "
+"JOIN `xyz` as d ON KEYS q"
+"ORDER BY d.eventTimestamp + "ASC " : "DESC "
+"LIMIT $limit OFFSET $offset"
How can I modify the above query, specially this part : d.* to something so that query execution time is faster, without breaking the original query logic.
Or is there another way to modify this query for faster execution.

Try use the LIMIT in the subquery.
CREATE INDEX ix1 ON xyz(id, timestamp DESC);
SELECT meta(d).id as ID, meta(d).cas as CAS, d.*
FROM (SELECT RAW m.id
FROM `xyz` as t
WHERE t.id is NOT NULL
GROUP BY t.id
LETTING m = MAX([t.timestamp, {t.timestamp, META(t).id}])[1]
ORDER BY m.timestamp DESC LIMIT $limit) as q
JOIN `xyz` as d ON KEYS q
ORDERBY d.timestamp;

Related

MySql Inner Join Query

I'm using mysql connector to connect visual basic with mysql,i m doing mysql query with 3 tables and i tried with inner join and the "normal mode" with the "normal mode" said not unique table/alias and with inner join the datagrid doesnt load anything,the three table are this ones
Order(N_Order,Date,Client Number)
Line_Order(N_Order,product_code,quantity)
Product(product_code,name,price)
and the mysql query with innerjoin is:
"SELECT c.name, COUNT( b.product_code ) AS cnt FROM order a " & _
"INNER JOIN line_order b ON a.number_order = b.number_order " & _
"INNER JOIN product c ON b.product_code = c.product_code " & _
"GROUP BY c.name " & _
"ORDER BY cnt DESC "
and the normal way is:
"SELECT product.name, COUNT( order_line.product_code ) AS cnt
FROM order, product, order_line where order.number_order = order_line.number_order
AND order_line.product_code = product.product_code
GROUP BY product.name
ORDER BY cnt DESC
LIMIT 0 , 5"
When i run the 2ยบ mysql query in phpmyadmin it works perfectly but when i run it in visual basic it gives me the error not unique tables alias/order i dont know what to do can someone help me please??
Put backticks ` around the table `order` as it conflicts with the reserved keyword in ORDER BY.
Its Solved it was from the datagridview size was too little for the data,2 hours on this because of the datagridview size,thanks guys for the help

Number rows of query result with index number

After some help I have my top ten results from my database. But there is no number that specifies the order. The user currently has to look at the data to understand if the data is ascending or descending order. I would like each piece of data to have a number to specify the ranking.
I am not sure how to go about this, so advice rather than code would be sufficient. A little confused and would rather consult someone who knows what they are doing before I start breaking my code.
Sorry i forgot to add my code:
$result = mysql_query("SELECT coffeeshops.*, services.*, sum(temp.total) as final_total FROM coffeeshops inner join services on coffeeshops.shop_id=services.shop_id
inner join (
select
SUM(comfort + service + ambience + friendliness + spacious + experience + bud_quality + bud_price + drink_price + space_cake + accessibility + toilet_access)/(12) /COUNT(shop_id) AS total, shop_id FROM ratings GROUP BY shop_id
) as temp on coffeeshops.shop_id=temp.shop_id
GROUP BY shop_name
ORDER BY final_total DESC, shop_name ASC limit 10");
while($row = mysql_fetch_array($result)) {
OUTPUT HTML here
}
Michael's solution will work, but you can also use PHP. If you have an array of your results $results, you can sort it, and use a for loop to print out the result number. For example:
sort($results); //Asc order, or use rsort($results) for Desc order
for($i=0; $i<count($results); $i++) {
echo $results[$i].' Rank #: '.($i + 1);
}
This works to create an incrementing column rank, if I understand your question:
SELECT
#rownum:=#rownum+1 `rank`,
column1
FROM table, (SELECT #rownum:=0) r
ORDER BY column1 DESC
LIMIT 10;
In order to use this with a GROUP BY and aggregates, you will probably need to wrap it in a subquery and place the #rownum incrementer in the outer query.
Example:
SELECT
#rownum:=#rownum+1 `rank`,
column1,
column1_count
FROM (
SELECT
column1,
COUNT(column1) column1_count
FROM table
GROUP BY column1
ORDER BY COUNT(column1) DESC
) c,
(SELECT #rownum:=0) r
LIMIT 10;

Group by subkey but if new read if not 1 show 0

Ok I know this is going to sound stupid. But I have tried everything.
Here is my code to start of with
SELECT toD.username AS ToUser,
fromD.username AS FromUser,
rvw.* FROM usermessages AS rvw
LEFT JOIN users AS toD
ON toD.id = rvw.touserid
LEFT JOIN users AS fromD ON fromD.id = rvw.fromuserid
WHERE touserid = '" . $this->userid . "'
AND deleted = '0'
GROUP BY subkey
ORDER BY rvw.read ASC, rvw.created DESC
while this does work, what I am finding is that if there is a new message, and the read is 0 it still shows up as 1. I know this is because I am grouping the rows together.
But am not sure of any other way to do this.
It doesn't work because mysql can return any row from the group no matter how you try to order your set. To find first row in the group using some custom order you have to split it into two tasks - first finding all distinct values for the column you group by and then finding first row in the subquery for every referenced value. So your query should look like:
SELECT toD.username AS ToUser, fromD.username as FromUser, msg.* FROM
( SELECT DISTINCT touserid, subkey
FROM usermessages
WHERE touserid = 'insert_your_id_here'
AND deleted=0 ) msgg
JOIN usermessages msg
ON msg.id = ( SELECT msgu.id
FROM usermessages msgu
WHERE msgu.touserid = msgg.touserid
AND msgu.subkey = msgg.subkey
AND deleted=0
ORDER BY msgu.read ASC, msgu.created DESC
LIMIT 1 )
JOIN users fromD ON msg.fromuserid = fromD.id
JOIN users toD ON msg.touserid = toD.id
Make sure you have an index on (touserid,subkey). Depending on how big your db is you may need more.

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;

Distinct Popular Hits

Can someone help me with this query:
SELECT su.name,su.imdb , su.id, su.owner, COUNT(*) AS count
FROM subhits AS h LEFT JOIN subtitles AS su ON h.subid=su.id
WHERE su.added BETWEEN '" . $lweek . "' AND '" . $today . "'
GROUP BY h.subid
ORDER BY count DESC LIMIT 15
RETURNS:
name imdb id owner count
*Angels and Demons WTV /title/tt0808151/ 3337 3055 120
Terminator Salvation 2009 /title/tt0438488/ 3539 26 120
Friday The 13th-WTV /title/tt0758746/ 3334 26 82
Night at the Museum /title/tt1078912/ 3548 7170 75
*Angels and Demons WTV2 /title/tt0808151/ 3512 12 10
*DUPLICATED IMDB
As you see it returns results with the same imdb.
What i would like to do is get the highest count, but exclude the lowest imdb count from the result.
What I like about MySQL compared to Oracle, is how other fields not part of GROUP BY can be selected without using grouping functions. What the query below does is take your query and groups it by imdb, which selects a unique imdb with the highest count (which would appear first in the descending sort in the subselect). Try it and see if it works for you.
SELECT name, imdb, id, owner, count
FROM
(
SELECT su.name,su.imdb , su.id, su.owner, COUNT(*) AS count
FROM subhits AS h LEFT JOIN subtitles AS su ON h.subid=su.id
WHERE su.added BETWEEN '" . $lweek . "' AND '" . $today . "'
GROUP BY h.subid
ORDER BY count DESC
)
GROUP BY imdb
LIMIT 15
This may help.
http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#101
I hate to say this, but this is one of those rare occasions where a temp table might help. If you put the results of this:
select
imdb,
id,
count(*) as cnt
from subtitles
group by
imdb,
id
..into a temp table, you can then get the rows you really want:
select
t.imdb,
t.id,
t.cnt
from MyTempTable t
inner join
(
select
imdb,
max(cnt) as maxcnt
from MyTempTable
group by
imdb
) as drv on t.imdb = drv.imdb and t.cnt = drv.maxcnt
..and the results of the above can be joined back into your main table without having to be grouped again.
Does this help?
Apologies for not putting all the SQL in but I'm pressed for time. This will do what you want but will still duplicate if the counts are the same. The query could be modified to deal with this if you care about it.
On a separate note, I'm not sure why you are left joining in the statement when you are not showing any data from the left hand table?
Try this:
SELECT su.name
, su.imdb
, su.id
, su.owner
, (SELECT COUNT(*) FROM dbo.subhits AS h WHERE h.subid = su.id) AS count
FROM dbo.subtitles AS su
ORDER BY count DESC LIMIT 15
Edit: Using the additional information provided I had an almost working solution but got stuck. Combining Chris Simpson's answer with the partial solution I came up with this. It avoids temp tables and has the missing pieces that the other Chris didn't have time to complete. I'm building this in MSSQL so it might need tweaking to work in MySQL. I also can't guarantee the information will be correct without your data but this might help.
SELECT a.id
, (SELECT su.name FROM dbo.subtitles su WHERE a.id = su.id LIMIT 1)
, a.imdb
, (SELECT su.owner FROM dbo.subtitles su WHERE a.id = su.id LIMIT 1)
, a.count
FROM
(
SELECT su.id
, su.imdb
, COUNT(*) AS count
FROM dbo.subtitles su
INNER JOIN dbo.subhits sh ON su.id = sh.subid
GROUP BY su.id, su.imdb
) a
INNER JOIN
(
SELECT c.imdb
, MAX(c.count) AS maxCount
FROM
(
SELECT su.id
, su.imdb
, COUNT(*) AS count
FROM dbo.subtitles su
INNER JOIN dbo.subhits sh ON su.id = sh.subid
GROUP BY su.id, su.imdb
) c
GROUP BY c.imdb
) b ON a.imdb = b.imdb AND a.count = b.maxCount
ORDER BY a.count DESC LIMIT 15
I'd try to test this myself, but I don't have your data or a good sample to test against.
SELECT su.name,su.imdb , su.id, su.owner, COUNT(*) AS counter
FROM subhits AS h LEFT JOIN subtitles AS su ON h.subid=su.id
WHERE su.added BETWEEN '" . $lweek . "' AND '" . $today . "'
GROUP BY h.subid
having max(counter)
ORDER BY count DESC LIMIT 15