-- Delete bad transaction(s)
DELETE M
 FROM 
 pmgr_ledger_entries LE,
 pmgr_tenders M
 WHERE 
 M.ledger_entry_id = LE.id AND
 LE.transaction_id
 IN (467);
DELETE LE
 FROM 
 pmgr_ledger_entries LE
 WHERE 
 LE.transaction_id
 IN (467);
DELETE SE
 FROM 
 pmgr_statement_entries SE
 WHERE 
 SE.transaction_id
 IN (467);
DELETE T
 FROM 
 pmgr_transactions T
 WHERE 
 T.id
 IN (467);

-- Delete bad transaction, one variable setting
SET @tid = 467;
DELETE M FROM  pmgr_ledger_entries LE, pmgr_tenders M
 WHERE M.ledger_entry_id = LE.id AND LE.transaction_id = @tid;
DELETE LE FROM pmgr_ledger_entries LE
 WHERE LE.transaction_id = @tid;
DELETE SE FROM pmgr_statement_entries SE
 WHERE SE.transaction_id = @tid;
DELETE T FROM pmgr_transactions T
 WHERE T.id = @tid;


-- Delete all but one customer
SET @cid = 6;
-- DELETE T FROM pmgr_transactions T
--  LEFT JOIN pmgr_customers C ON C.id = T.customer_id
--  WHERE C.id IS NOT NULL AND C.id <> @cid;
DELETE C FROM pmgr_customers C
 WHERE C.id <> @cid;
DELETE L FROM pmgr_leases L
 LEFT JOIN pmgr_customers C ON C.id = L.customer_id
 WHERE C.id IS NULL;
DELETE T FROM pmgr_transactions T
 LEFT JOIN pmgr_customers C ON C.id = T.customer_id
 WHERE C.id IS NULL;
DELETE SE FROM pmgr_statement_entries SE
 LEFT JOIN pmgr_customers C ON C.id = SE.customer_id
 WHERE C.id IS NULL;
DELETE LE FROM pmgr_ledger_entries LE
 LEFT JOIN pmgr_transactions T ON T.id = LE.transaction_id
 WHERE T.id IS NULL;
DELETE M FROM pmgr_tenders M
 LEFT JOIN pmgr_ledger_entries LE ON M.ledger_entry_id = LE.id
 WHERE LE.id IS NULL;
DELETE DE FROM pmgr_double_entries DE
 LEFT JOIN pmgr_ledger_entries LE ON LE.id = DE.debit_entry_id
 WHERE LE.id IS NULL;
DELETE DE FROM pmgr_double_entries DE
 LEFT JOIN pmgr_ledger_entries LE ON LE.id = DE.credit_entry_id
 WHERE LE.id IS NULL;
UPDATE pmgr_ledger_entries LE, pmgr_ledgers L, pmgr_accounts A
 SET LE.ledger_id = L.id
 WHERE A.id = LE.account_id AND L.account_id = A.id AND L.sequence = 1;
DELETE FROM pmgr_ledgers WHERE sequence > 1;
UPDATE pmgr_ledgers SET prior_ledger_id = NULL, close_transaction_id = NULL;


-- Delete a ledger entry, associated double entry, and matching ledger_entry
SET @leid = 1365;
DELETE FROM pmgr_ledger_entries WHERE id = @leid;
DELETE DE FROM pmgr_double_entries DE
 LEFT JOIN pmgr_ledger_entries LE ON LE.id = DE.debit_entry_id
 WHERE LE.id IS NULL;
DELETE DE FROM pmgr_double_entries DE
 LEFT JOIN pmgr_ledger_entries LE ON LE.id = DE.credit_entry_id
 WHERE LE.id IS NULL;
DELETE LE FROM pmgr_ledger_entries LE
 LEFT JOIN pmgr_double_entries DE 
   ON DE.credit_entry_id = LE.id OR DE.debit_entry_id = LE.id
 WHERE DE.id IS NULL;

-- Add and update every Tender.ledger_entry_id (for rolling up old databases)
-- Takes a while to complete (~30s at time of writing)
ALTER TABLE `pmgr_tenders`
 ADD `deposit_ledger_entry_id` INT UNSIGNED DEFAULT NULL
 AFTER `nsf_ledger_entry_id`;
UPDATE
pmgr_tenders Tnd
JOIN pmgr_tender_types TndT ON TndT.id = Tnd.tender_type_id
JOIN pmgr_transactions T ON T.id = Tnd.deposit_transaction_id
JOIN pmgr_ledger_entries LE ON LE.transaction_id = T.id AND LE.account_id = TndT.account_id
JOIN pmgr_double_entries DE ON DE.debit_entry_id = LE.id OR DE.credit_entry_id = LE.id
JOIN pmgr_ledger_entries LEd ON (DE.debit_entry_id = LEd.id OR DE.credit_entry_id = LEd.id)
    AND LEd.id <> LE.id    
SET Tnd.deposit_ledger_entry_id = LEd.id;


-- Add auto_deposit and deposit_account_id to tenders
ALTER TABLE `pmgr_tender_types`
 ADD `auto_deposit` TINYINT(1) UNSIGNED DEFAULT '0' NOT NULL
 AFTER `tillable`;
ALTER TABLE `pmgr_tender_types`
 ADD `deposit_account_id` INTEGER(10) UNSIGNED DEFAULT NULL
 AFTER `account_id`;


-- Determine economic conditions
SELECT `status`, COUNT(id), SUM(rent) FROM pmgr_units
GROUP BY `status` WITH ROLLUP;


-- Check that transaction totals add up correctly
SELECT T.id, T.type, T.amount,
-- T.type, A.type, E.crdr,
 SUM(IF(E.account_id = T.account_id,
        IF(A.type IN ('ASSET','EXPENSE') XOR E.crdr='DEBIT',-1,1),0)
     *E.amount) AS Tamt,  
 SUM(IF(E.account_id = T.account_id,
        0,IF(A.type IN ('ASSET','EXPENSE') XOR E.crdr='DEBIT',-1,1))
     *E.amount) AS Oamt,  
 COUNT(E.id) AS Ecnt
FROM pmgr_transactions T
-- LEFT JOIN pmgr_statement_entries E ON E.transaction_id = T.id  
 LEFT JOIN pmgr_ledger_entries E ON E.transaction_id = T.id 
 LEFT JOIN pmgr_accounts A ON A.id = T.account_id -- E.account_id
-- WHERE 
 -- E.account_id != T.account_id
 GROUP BY T.id 
   HAVING
    (T.type = 'INVOICE' AND Tamt <> T.amount) 
      OR      
    (T.type <> 'INVOICE' AND Oamt <> T.amount)    
      OR      
    (Tamt * -1 <> Oamt)


-- Verify that statement entries all have the correct type
SELECT SE.id, SE.type, T.id, T.type
 FROM pmgr_statement_entries SE
 LEFT JOIN pmgr_transactions T ON T.id = SE.transaction_id 
WHERE
 ((T.type = 'RECEIPT' OR T.type = 'CREDIT_NOTE') AND
  SE.type NOT IN ('DISBURSEMENT', 'WAIVER', 'REVERSAL', 'WRITEOFF', 'SURPLUS')
 ) 
 OR
 ((T.type = 'INVOICE' OR T.type = 'PAYMENT') AND
  SE.type NOT IN ('CHARGE', 'PAYMENT', 'REFUND')
 )  
 -- catch other types not considered in this query
 OR T.type NOT IN ('RECEIPT', 'CREDIT_NOTE', 'INVOICE', 'PAYMENT')




-- #################################################################
-- #################################################################
-- #################################################################
-- #################################################################
-- #################################################################
-- #################################################################
-- #################################################################
-- #################################################################
-- #################################################################
-- ## USER / GROUP

INSERT INTO pmgr_groups (`code`, `name`, `rank`)
 VALUES('Owner', 'Owner Group', 25);
SET @o_gid = LAST_INSERT_ID();

INSERT INTO pmgr_groups (`code`, `name`, `rank`)
 VALUES('Admin', 'Admin Group', 50);
SET @a_gid = LAST_INSERT_ID();

INSERT INTO pmgr_groups (`code`, `name`, `rank`)
 VALUES('Manager', 'Manager Group', 75);
SET @m_gid = LAST_INSERT_ID();

INSERT INTO pmgr_groups (`code`, `name`)
 VALUES('Temp', 'Temporary Help');
SET @t_gid = LAST_INSERT_ID();

INSERT INTO pmgr_users (`code`, `login`, `contact_id`)
 VALUES('AP', 'abijah', 0);
SET @a_uid = LAST_INSERT_ID();

INSERT INTO pmgr_users (`code`, `login`, `contact_id`)
 VALUES('SK', 'shirley', 0);
SET @s_uid = LAST_INSERT_ID();

INSERT INTO pmgr_users (`code`, `login`, `contact_id`)
 VALUES('DE', 'dan', 0);
SET @d_uid = LAST_INSERT_ID();

INSERT INTO pmgr_users (`code`, `login`, `contact_id`)
 VALUES('KD', 'kevin', 0);
SET @k_uid = LAST_INSERT_ID();

INSERT INTO pmgr_sites (`code`, `name`)
 VALUES('VSS', 'Valley Storage');
SET @v_sid = LAST_INSERT_ID();

INSERT INTO pmgr_sites (`code`, `name`)
 VALUES('FAKE', 'Fake Site');
SET @f_sid = LAST_INSERT_ID();

-- Site Membership

INSERT INTO pmgr_site_memberships (`site_id`, `user_id`, `group_id`)
 VALUES(@v_sid, @a_uid, @o_gid);
INSERT INTO pmgr_site_memberships (`site_id`, `user_id`, `group_id`)
 VALUES(@v_sid, @a_uid, @a_gid);
INSERT INTO pmgr_site_memberships (`site_id`, `user_id`, `group_id`)
 VALUES(@v_sid, @a_uid, @m_gid);
INSERT INTO pmgr_site_memberships (`site_id`, `user_id`, `group_id`)
 VALUES(@v_sid, @s_uid, @m_gid);
INSERT INTO pmgr_site_memberships (`site_id`, `user_id`, `group_id`)
 VALUES(@v_sid, @d_uid, @t_gid);
INSERT INTO pmgr_site_memberships (`site_id`, `user_id`, `group_id`)
 VALUES(@f_sid, @s_uid, @a_gid);
INSERT INTO pmgr_site_memberships (`site_id`, `user_id`, `group_id`)
 VALUES(@f_sid, @s_uid, @m_gid);
INSERT INTO pmgr_site_memberships (`site_id`, `user_id`, `group_id`)
 VALUES(@f_sid, @k_uid, @o_gid);
INSERT INTO pmgr_site_memberships (`site_id`, `user_id`, `group_id`)
 VALUES(@f_sid, @d_uid, @t_gid);


-- Options

INSERT INTO pmgr_options (`name`) VALUES ('theme');
SET @t_oid = LAST_INSERT_ID();
INSERT INTO pmgr_options (`name`) VALUES ('menu');
SET @m_oid = LAST_INSERT_ID();

-- Default Option Values

INSERT INTO pmgr_option_values (`option_id`, `value`) VALUES (@t_oid, 'blue');
INSERT INTO pmgr_default_options (`option_value_id`) VALUES(LAST_INSERT_ID());
INSERT INTO pmgr_option_values (`option_id`, `value`) VALUES (@m_oid, 'basic');
INSERT INTO pmgr_default_options (`option_value_id`) VALUES(LAST_INSERT_ID());

-- Group options

INSERT INTO pmgr_option_values (`option_id`, `value`) VALUES (@t_oid, 'gold');
INSERT INTO pmgr_group_options (`group_id`, `option_value_id`)
 VALUES(@o_gid, LAST_INSERT_ID());
INSERT INTO pmgr_option_values (`option_id`, `value`) VALUES (@t_oid, 'silver');
INSERT INTO pmgr_group_options (`group_id`, `option_value_id`)
 VALUES(@a_gid, LAST_INSERT_ID());
INSERT INTO pmgr_option_values (`option_id`, `value`) VALUES (@t_oid, 'red');
INSERT INTO pmgr_group_options (`group_id`, `option_value_id`)
 VALUES(@m_gid, LAST_INSERT_ID());

INSERT INTO pmgr_option_values (`option_id`, `value`) VALUES (@m_oid, 'advanced');
INSERT INTO pmgr_group_options (`group_id`, `option_value_id`)
 VALUES(@o_gid, LAST_INSERT_ID());
INSERT INTO pmgr_option_values (`option_id`, `value`) VALUES (@m_oid, 'advanced');
INSERT INTO pmgr_group_options (`group_id`, `option_value_id`)
 VALUES(@a_gid, LAST_INSERT_ID());
INSERT INTO pmgr_option_values (`option_id`, `value`) VALUES (@m_oid, 'restricted');
INSERT INTO pmgr_group_options (`group_id`, `option_value_id`)
 VALUES(@t_gid, LAST_INSERT_ID());

-- User Options
INSERT INTO pmgr_option_values (`option_id`, `value`) VALUES (@m_oid, 'special');
INSERT INTO pmgr_user_options (`user_id`, `option_value_id`)
 VALUES(@s_uid, LAST_INSERT_ID());

-- Site Options
INSERT INTO pmgr_option_values (`option_id`, `value`) VALUES (@t_oid, 'site-theme');
INSERT INTO pmgr_site_options (`site_id`, `option_value_id`)
 VALUES(@f_sid, LAST_INSERT_ID());


-- SELECT U.id, P.name, MAX(P.access)
--  FROM pmgr_users U
--    LEFT JOIN pmgr_site_membership   M ON M.user_id = U.id
--    LEFT JOIN pmgr_groups            G ON G.id = M.group_id
--    LEFT JOIN pmgr_group_permissions P ON P.group_id = G.id
-- GROUP BY U.id, P.name


-- User access to site
SELECT U.id, U.login, COUNT(G.id) AS 'groups', MIN(G.rank) AS highest_rank
 FROM pmgr_users U
   JOIN pmgr_site_memberships  M ON M.user_id = U.id
   JOIN pmgr_sites             S ON S.id = M.site_id
   JOIN pmgr_groups            G ON G.id = M.group_id
WHERE S.code = 'VSS'
GROUP BY U.id


-- User Options
SELECT O.id, O.name, O.default,
       GROUP_CONCAT(Uopt.value) AS 'value', COUNT(U.id) AS 'count'
 FROM pmgr_options O
   LEFT JOIN pmgr_user_options  Uopt ON Uopt.option_id = O.id
   LEFT JOIN pmgr_users         U    ON U.id = Uopt.user_id
WHERE U.id = 1
GROUP BY O.id

-- Group Options
SELECT O.id, O.name, O.default,
       GROUP_CONCAT(Gopt.value) AS 'value', COUNT(G.id) AS 'count'
 FROM pmgr_options O
   LEFT JOIN pmgr_group_options  Gopt ON Gopt.option_id = O.id
   LEFT JOIN pmgr_groups         G    ON G.id = Gopt.group_id
WHERE G.id = 1
GROUP BY O.id


-- Site Options
SELECT O.id, O.name, O.default,
       GROUP_CONCAT(Sopt.value) AS 'value', COUNT(S.id) AS 'count'
 FROM pmgr_options O
   LEFT JOIN pmgr_site_options  Sopt ON Sopt.option_id = O.id
   LEFT JOIN pmgr_sites         S    ON S.id = Sopt.site_id
WHERE S.id = 1
GROUP BY O.id


-- Option value for member & site
SELECT O.id, O.name, O.default,
       S.id AS site_id, Sopt.value,
       G.id AS group_id, Gopt.value,
       U.id AS user_id, Uopt.value
 FROM pmgr_options O
   LEFT JOIN pmgr_site_options  Sopt ON Sopt.option_id = O.id
   LEFT JOIN pmgr_sites         S    ON S.id = Sopt.site_id
   LEFT JOIN pmgr_group_options Gopt ON Gopt.option_id = O.id
   LEFT JOIN pmgr_groups        G    ON G.id = Gopt.group_id
   LEFT JOIN pmgr_user_options  Uopt ON Uopt.option_id = O.id
   LEFT JOIN pmgr_users         U    ON U.id = Uopt.user_id
WHERE O.name = 'theme'
--GROUP BY O.id



-- Option value for member & site
-- 1) User
SET @sid = 1;
SET @uid = 1;
SET @oid = 1;
SELECT O.name, U.id, Uopt.value
 FROM pmgr_options O
   JOIN pmgr_user_options      Uopt ON Uopt.option_id = O.id
   JOIN pmgr_users             U    ON U.id = Uopt.user_id
--   JOIN pmgr_site_memberships  M    ON M.user_id = U.id
--   JOIN pmgr_groups            G    ON G.id = M.group_id
--   JOIN pmgr_sites             S    ON S.id = M.site_id
WHERE -- S.id = @sid AND
     U.id = @uid AND O.id = @oid
;

-- 2) Group
SELECT O.name, G.rank, G.id, Gopt.value
 FROM pmgr_options O
   JOIN pmgr_group_options     Gopt ON Gopt.option_id = O.id
   JOIN pmgr_groups            G    ON G.id = Gopt.group_id
   JOIN pmgr_site_memberships  M    ON M.group_id = G.id
   JOIN pmgr_users             U    ON U.id = M.user_id
   JOIN pmgr_sites             S    ON S.id = M.site_id
WHERE S.id = @sid AND U.id = @uid AND O.id = @oid
ORDER BY G.rank
;

-- 3) Site
SELECT O.name, S.id, Sopt.value
 FROM pmgr_options O
   JOIN pmgr_site_options      Sopt ON Sopt.option_id = O.id
   JOIN pmgr_sites             S    ON S.id = Sopt.site_id
--    JOIN pmgr_site_memberships  M    ON M.site_id = S.id
--    JOIN pmgr_groups            G    ON G.id = M.group_id
--    JOIN pmgr_users             U    ON U.id = M.user_id
WHERE S.id = @sid
--      AND U.id = @uid
      AND O.id = @oid
;

-- 3) Default
SELECT O.name, O.default AS 'value'
 FROM pmgr_options O
WHERE O.id = @oid
;


-- User Permissions


-- Group Permissions

-- All option values, in order
SELECT O.name, V.value,
       U.id AS uid, G.id AS gid, S.id as sid,
       Dopt.id AS did, G.rank
 FROM pmgr_option_values V
   JOIN pmgr_options              O    ON O.id = V.option_id
   LEFT JOIN pmgr_user_options    Uopt ON Uopt.option_value_id = V.id
   LEFT JOIN pmgr_group_options   Gopt ON Gopt.option_value_id = V.id
   LEFT JOIN pmgr_site_options    Sopt ON Sopt.option_value_id = V.id
   LEFT JOIN pmgr_default_options Dopt ON Dopt.option_value_id = V.id
   LEFT JOIN pmgr_groups          G    ON G.id = Gopt.group_id
   LEFT JOIN pmgr_users           U    ON U.id = Uopt.user_id
   LEFT JOIN pmgr_sites           S    ON S.id = Sopt.site_id
WHERE O.id = @oid
ORDER BY IF(U.id IS NOT NULL, 1,
            IF (G.id IS NOT NULL, 2,
                IF (S.id IS NOT NULL, 3, 4))) ASC,
         IF (G.id IS NOT NULL, G.rank, 0) ASC


-- Option values relevant to the user and site, in order
SELECT O.name, V.value,
       U.id AS uid, G.id AS gid, S.id as sid,
       Dopt.id AS did, G.rank
 FROM pmgr_option_values V
   JOIN pmgr_options              O    ON O.id = V.option_id
   LEFT JOIN pmgr_user_options    Uopt ON Uopt.option_value_id = V.id
   LEFT JOIN pmgr_group_options   Gopt ON Gopt.option_value_id = V.id
   LEFT JOIN pmgr_site_options    Sopt ON Sopt.option_value_id = V.id
   LEFT JOIN pmgr_default_options Dopt ON Dopt.option_value_id = V.id
   LEFT JOIN pmgr_groups          G    ON G.id = Gopt.group_id
   LEFT JOIN pmgr_users           U    ON U.id = Uopt.user_id
   LEFT JOIN pmgr_sites           S    ON S.id = Sopt.site_id
   JOIN pmgr_site_memberships  M    ON M.user_id = U.id AND M.site_id = S.id
WHERE S.id = @sid AND U.id = @uid AND O.id = @oid
ORDER BY IF(U.id IS NOT NULL, 1,
            IF (G.id IS NOT NULL, 2,
                IF (S.id IS NOT NULL, 3, 4))) ASC,
         IF (G.id IS NOT NULL, G.rank, 0) ASC





SET @sid = 1;
SET @uid = 1;
SET @oid = 1;
SELECT O.name, V.value,
       U.id AS uid,
		 -- G.id AS gid,
		 S.id as sid,
       Dopt.id AS did
		 -- G.rank
 FROM pmgr_option_values V
   JOIN pmgr_options              O    ON O.id = V.option_id
   LEFT JOIN pmgr_user_options    Uopt ON Uopt.option_value_id = V.id
   LEFT JOIN pmgr_site_options    Sopt ON Sopt.option_value_id = V.id
--   LEFT JOIN pmgr_users           U    ON U.id = Uopt.user_id
--   LEFT JOIN pmgr_group_options   Gopt ON Gopt.option_value_id = V.id
   LEFT JOIN pmgr_default_options Dopt ON Dopt.option_value_id = V.id
--   LEFT JOIN pmgr_groups          G    ON G.id = Gopt.group_id
   LEFT JOIN pmgr_users           U    ON U.id = Uopt.user_id
   LEFT JOIN pmgr_sites           S    ON S.id = Sopt.site_id
   JOIN pmgr_site_memberships     M    ON M.user_id = U.id -- AND M.site_id = S.id
WHERE -- S.id = @sid AND U.id = @uid AND 
  O.id = @oid
ORDER BY IF(U.id IS NOT NULL, 1,
--            IF (G.id IS NOT NULL, 2,
                IF (S.id IS NOT NULL, 3, 4)) -- ) ASC,
--         IF (G.id IS NOT NULL, G.rank, 0) ASC





-- ------------------------------------------------------------
-- ------------------------------------------------------------
-- ------------------------------------------------------------
--  Working version (without defaults)
SET @sid = 1;
SET @uid = 1;
SET @oid = 1;
SELECT O.name, O.id AS oid, V.value, V.id AS vid,
       U.id AS uid,
       G.id AS gid,
       S.id AS sid,
--       Dopt.id AS did
       G.rank
 FROM pmgr_users U
   JOIN pmgr_site_memberships     M ON M.user_id = U.id
   JOIN pmgr_sites                S ON S.id = M.site_id
   LEFT JOIN pmgr_groups          G ON G.id = M.group_id
   LEFT JOIN pmgr_user_options    Uopt ON Uopt.user_id  = U.id
   LEFT JOIN pmgr_group_options   Gopt ON Gopt.group_id = G.id
   LEFT JOIN pmgr_site_options    Sopt ON Sopt.site_id  = S.id
   LEFT JOIN pmgr_option_values   V    ON (V.id = Uopt.option_value_id OR
                                           V.id = Gopt.option_value_id OR
                                           V.id = Sopt.option_value_id)
   JOIN pmgr_options              O    ON O.id = V.option_id
WHERE S.id = @sid AND U.id = @uid AND O.id = @oid
ORDER BY IF(U.id IS NOT NULL, 1,
            IF (G.id IS NOT NULL, 2,
                IF (S.id IS NOT NULL, 3, 4))) ASC,
         IF (G.id IS NOT NULL, G.rank, 0) ASC
;




SET @sid = 1;
SET @uid = 1;
SET @oid = 1;
SELECT O.name, O.id AS oid, V.value, V.id AS vid,
       U.id AS uid,
       G.id AS gid,
       S.id AS sid,
--       Dopt.id AS did
       G.rank
 FROM pmgr_options O
   LEFT JOIN pmgr_option_values     V    ON V.option_id = O.id
   -- Now have the option and all possible values
   LEFT JOIN pmgr_user_options      Uopt ON Uopt.option_value_id = V.id
   LEFT JOIN pmgr_group_options     Gopt ON Gopt.option_value_id = V.id
   LEFT JOIN pmgr_site_options      Sopt ON Sopt.option_value_id = V.id
   -- Now have the user/group/site that each value applies to
   LEFT JOIN pmgr_users U           U    ON Uopt.user_id = U.id OR Uopt.user_id IS NULL
   -- Now restricted to our user
        JOIN pmgr_site_memberships  M    ON M.user_id = U.id
        JOIN pmgr_sites             S    ON S.id = M.site_id



   ON O.id = V.option_id
   LEFT JOIN pmgr_groups          G ON G.id = M.group_id
   LEFT JOIN pmgr_option_values   V    ON (V.id = Uopt.option_value_id OR
                                           V.id = Gopt.option_value_id OR
                                           V.id = Sopt.option_value_id)
   JOIN 
WHERE S.id = @sid AND U.id = @uid AND O.id = @oid
ORDER BY IF(U.id IS NOT NULL, 1,
            IF (G.id IS NOT NULL, 2,
                IF (S.id IS NOT NULL, 3, 4))) ASC,
         IF (G.id IS NOT NULL, G.rank, 0) ASC
;









SET @sid = 1;
SET @uid = 1;
SET @oid = 1;
SELECT O.name, O.id AS oid, V.value, V.id AS vid,
       U.id AS uid,
       G.id AS gid,
       S.id AS sid,
--       Dopt.id AS did
       G.rank
 FROM pmgr_options O LEFT JOIN pmgr_option_values V ON V.option_id = O.id,
   pmgr_users U
   JOIN pmgr_site_memberships     M ON M.user_id = U.id
   JOIN pmgr_sites                S ON S.id = M.site_id
   LEFT JOIN pmgr_groups          G ON G.id = M.group_id
   LEFT JOIN pmgr_user_options    Uopt ON Uopt.user_id  = U.id
   LEFT JOIN pmgr_group_options   Gopt ON Gopt.group_id = G.id
   LEFT JOIN pmgr_site_options    Sopt ON Sopt.site_id  = S.id,
WHERE S.id = @sid AND U.id = @uid AND O.id = @oid
  AND (V.id = Uopt.option_value_id OR
       V.id = Gopt.option_value_id OR
       V.id = Sopt.option_value_id)
ORDER BY IF(U.id IS NOT NULL, 1,
            IF (G.id IS NOT NULL, 2,
                IF (S.id IS NOT NULL, 3, 4))) ASC,
         IF (G.id IS NOT NULL, G.rank, 0) ASC
;
