We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 5340
    • 1,624 Posts
    Hi,

    Is it possible to get all the information related to a document in one sql query?

    Currently I do it 2 steps

    1. get documents from site_content
    2. loop through the documents and get the TV values using getTemplateVarOutput

    Something like

    $sql = "SELECT * FROM $table WHERE template = 47 AND isfolder = 1 AND deleted = 0 AND published = 1 AND hidemenu = 0 ORDER BY menuindex";
    $rs= $modx->db->query($sql); 
    
    while($doc = $modx->db->getRow($rs)){
        $tv = $modx->getTemplateVarOutput(array('location','code'),$doc['id']);
    }


    How would you do the above in one query and have the TV names as table headers in the sql result?


    Thank you
      • 4172
      • 5,888 Posts
      there is a function I have written for bloX which generates a sql-query from given parameters for blox to get documents and tvs in with one query.

      see http://github.com/Bruno17/bloX-Xedit/blob/master/snippets/blox/inc/blox.class.inc.php

      about line 1193

      if you call bloX for example like that:

      [!bloX? &fields=`pagetitle,longtitle,myfirstTV,mysecondTV`&filter=`myfirstTV|test|%LIKE%++mysecondTV|200|gt`&parents=`15,45`&orderBy=`menuindex`!]


      the function getdocs generates together with the function filter2sqlwhere and other helperfunctions the needed sql-statement for this.
      of course this cannot get processed TV-output with bindings, but gets also default-values, if value is empty
        -------------------------------

        you can buy me a beer, if you like MIGX

        http://webcmsolutions.de/migx.html

        Thanks!
        • 5340
        • 1,624 Posts
        It seems it’s what I need.

        Thank you.

          • 4172
          • 5,888 Posts
          if I call

          [!bloX? &fields=`location,code`!]


          it generates:

          SELECT distinct IF(location_tvcv.value!='',location_tvcv.value,location_tv.default_text) AS location , IF(code_tvcv.value!='',code_tvcv.value,code_tv.default_text) AS code , sc.id , sc.pagetitle , sc.published FROM (`d00c44c7`.`modx_site_content` AS sc,`d00c44c7`.`modx_site_tmplvars` AS location_tv ,`d00c44c7`.`modx_site_tmplvars` AS code_tv ) LEFT JOIN `d00c44c7`.`modx_site_tmplvar_contentvalues` AS location_tvcv ON location_tvcv.contentid = sc.id AND location_tvcv.tmplvarid = location_tv.id LEFT JOIN `d00c44c7`.`modx_site_tmplvar_contentvalues` AS code_tvcv ON code_tvcv.contentid = sc.id AND code_tvcv.tmplvarid = code_tv.id WHERE 1 AND location_tv.name = 'location' AND code_tv.name = 'code' AND sc.`parent`IN(9999999) AND sc.`published`="1" AND sc.`deleted`="0" ORDER BY sc.menutitle
            -------------------------------

            you can buy me a beer, if you like MIGX

            http://webcmsolutions.de/migx.html

            Thanks!
            • 5340
            • 1,624 Posts
            Even more helpful

            Thanks
              • 5340
              • 1,624 Posts
              I ended up with this

              SELECT 
              
              	distinct 
              		
              		sc.id,
              		sc.pagetitle, 
              		
              		IF(location_tvcv.value!='',location_tvcv.value,location_tv.default_text) AS location , 
              		IF(code_tvcv.value!='',code_tvcv.value,code_tv.default_text) AS code
              		
              		FROM (
              			`modx_site_content` AS sc,
              			
              			`modx_site_tmplvars` AS location_tv,
              			
              			`modx_site_tmplvars` AS code_tv 
              		) 
              		
              		LEFT JOIN 
              			
              			`modx_site_tmplvar_contentvalues` AS location_tvcv ON location_tvcv.contentid = sc.id AND 
              			
              			location_tvcv.tmplvarid = location_tv.id LEFT JOIN `modx_site_tmplvar_contentvalues` AS code_tvcv ON code_tvcv.contentid = sc.id AND 
              			
              			code_tvcv.tmplvarid = code_tv.id WHERE 1 AND 
              			
              			location_tv.name = 'location' AND 
              			
              			code_tv.name = 'code' AND 
              			
              			sc.`parent` = 1269 AND 
              			
              			sc.`published`= 1 AND 
              			
              			sc.`deleted`= 0  AND
              			
              			sc.`hidemenu`= 0  AND
              			
              			sc.`template`= 4  
              			
              		ORDER BY 
              			
              				sc.pagetitle
                • 9207 ☆ A M B ☆
                • 2,475 Posts
                I like getting things in one query if I can, but getting the TVs for documents can make for some insanely difficult MySQL JOIN statements, and as frustrating as it might seem, it might be much much easier and faster to use multiple queries to assemble your data. Just a thought.... the proof is in the pudding.
                  • 4172
                  • 5,888 Posts
                  but... if you want to filter, sort, limit (for pagination for example), have mysql-genarated-fields and so on IMO its easier and better to have it all in one query, instaed to get the whole table and filter out and sort and so on in foreach-loops.
                  that was the reason to create this functions for bloX, which generates the needed mysql-statement from given parameters &filter &orderBy &fields &groupBy &parents &documents &perPage &pageStart
                    -------------------------------

                    you can buy me a beer, if you like MIGX

                    http://webcmsolutions.de/migx.html

                    Thanks!
                    • 5340
                    • 1,624 Posts
                    For me its 1 query vs 501. I have 500 entries that I need to show in a table.

                    Now that I know how to do it it’s easy.
                      • 9207 ☆ A M B ☆
                      • 2,475 Posts
                      Yeah, there’s an art to getting everything in as few queries as possible. I’ve had to write logic at times that would do 3 queries:
                      1. Select the IDs that matched the criteria in the order that they needed to be returned (i.e. only 10 results per page)
                      2. Select the data from those IDs
                      3. Count the total number of records for proper pagination.

                      I haven’t formalized the structure that emerged, but I could see it was definitely a pattern that would recur for complex queries.