views:

153

answers:

3

I am looking for a tip on how to optimize this....

SELECT   u.uid,
         u.username,
         u.nid,
         wd.pay
FROM     (users_data AS u
          LEFT JOIN winners_data wd
            ON u.nid = wd.nid
               AND u.uid = wd.uid)
         LEFT JOIN dp_node dn
           ON u.nid = dn.nid
WHERE    u.uid = ".$val."
         AND ((dn.TYPE = 'event'
               AND (SELECT Count(nid)
                    FROM   tournament_event
                    WHERE  nid = u.nid
                           AND type_value IN ('A','B','C')) > 0)
               OR (dn.TYPE = 'new_event'
                   AND (SELECT Count(nid)
                        FROM   user_tournament_event
                        WHERE  nid = u.nid
                               AND type_0_value IN ('Y','X')) > 0))
ORDER BY nid ASC

Actually the $val is nothing but the uid that comes from the following query one at a time as a part of my loop.

SELECT DISTINCT(dump.uid) FROM leader_Jdump AS dump

Is there any way to add this part as well to the above query? I guess it will be faster if I can do it at the MySQL level.

+4  A: 

Try this:

SELECT  u.uid, u.username, u.nid, wd.pay
FROM    users_data AS u
LEFT JOIN
        winners_data wd
ON      (wd.nid, wd.uid) = (u.nid, u.uid)
JOIN    dp_node dn 
ON      dn.nid = u.nid
        AND dn.type IN ('event', 'new_event')
WHERE   u.uid = ".$val."
        AND EXISTS
        (
        SELECT  NULL
        FROM    tournament_event te
        WHERE   te.nid = u.nid
                AND type_value IN ('A', 'B', 'C')
                AND dn.type = 'event'
        UNION ALL
        SELECT  NULL
        FROM    user_tournament_event te
        WHERE   te.nid = u.nid
                AND type_0_value IN ('X', 'Y')
                AND dn.type = 'new_event'

        )
ORDER BY
        u.nid ASC

I removed OUTER JOIN from dp_node, since your original query required a non-NULL condition on a dp_node field in WHERE clause, so LEFT JOIN is useless here.

Create the following indexes:

users_data (uid, nid)
winners_data (uid, nid)
dp_node (nid, event_type)
tournament_event (nid, type_value)
user_tournament_event (nid, type_0_value)
Quassnoi
Damn you Quassnoi, you are fast.
Leonel Martins
`@Leonel`: You snooze, you lose!
Quassnoi
@Lionel: You're anthropomorhizing a shell script
OMG Ponies
`@rexem`: and we shell scripts just hate being anthropomorphized!
Quassnoi
Thanks.But there is no reference to the user_tournament_event table that was mentioned in my original post (before being formatted). Please check the livejournal link mentioned above.
shantanuo
`@shantanuo`: fixed.
Quassnoi
A: 

This might be equivalent, but easier to read:

WITH NIDs(type_value,nid) AS (
  SELECT 'event', nid FROM tournament_event
  WHERE type_value IN ('A','B','C')
  UNION ALL
  SELECT 'new_event', nid FROM user_tournament_event
  WHERE type_value IN ('X','Y')
)

SELECT
  u.uid,
  u.username,
  u.nid,
  wd.pay
FROM users_data AS u JOIN NIDs AS n
ON n.nid = u.nid
AND n.type_value = u."type"
LEFT JOIN winners_data AS wd
ON u.nid=wd.nid AND u.uid=wd.uid
LEFT JOIN dp_node AS dn 
ON u.nid = dn.nid
WHERE u.uid=".$val."
ORDER BY nid ASC

If "what kind of event" is an important one, you would be better off with a single table from which you can make that determination by looking at a single column or two. You seem to have two tables holding this information (tournament_event and user_tournament_event). For example, you could store information as in the NIDs expression of this query.

Added on 2009-08-22:

Here's the same query, with the CTE expressed as a derived table:

SELECT
  u.uid,
  u.username,
  u.nid,
  wd.pay
FROM users_data AS u JOIN (
  SELECT 'event', nid FROM tournament_event
  WHERE type_value IN ('A','B','C')
  UNION ALL
  SELECT 'new_event', nid FROM user_tournament_event
  WHERE type_value IN ('X','Y')
) AS n(type_value,nid)
ON n.nid = u.nid
AND n.type_value = u."type"
LEFT JOIN winners_data AS wd
ON u.nid=wd.nid AND u.uid=wd.uid
LEFT JOIN dp_node AS dn 
ON u.nid = dn.nid
WHERE u.uid=".$val."
ORDER BY nid ASC
Steve Kass
FWIW, MySQL does not support CTE's.
Bill Karwin
@Bill: No CTE support is no problem, because the CTE can be rewritten as a derived table. I'll add that rewriting to my answer, but I'll leave the CTE, which might be easier for people to read. And some day, MySQL will probably support it, since it's been part of the ANSI/ISO standard for a while.
Steve Kass
A: 

I've seen this style (all of the closing parenthesis at the end of a single line) and wonder how people can make sense of it. Someone asked earlier for a reformatted version:

SELECT    u.uid,
          u.username,
          u.nid,
          wd.pay
FROM      users_data u
          LEFT JOIN winners_data wd
               ON u.nid = wd.nid
               AND u.uid = wd.uid
          LEFT JOIN dp_node dn
               ON u.nid = dn.nid
WHERE     u.uid = ".$val."
          AND (
                (
                    dn.TYPE = 'event'
                    AND (
                        SELECT Count(nid)
                        FROM   tournament_event
                        WHERE  nid = u.nid
                               AND type_value IN ('A','B','C')
                    ) > 0
                )
                OR (
                    dn.TYPE = 'new_event'
                    AND (
                        SELECT Count(nid)
                        FROM   user_tournament_event
                        WHERE  nid = u.nid
                               AND type_0_value IN ('Y','X')
                    ) > 0
                )
          )
ORDER BY  nid ASC
Chris Judge