The "Right" Way to Join Two Lists In a DVWP

As long as I’ve been working with Data View Web Parts (DVWPs), I’ve pretty much always done my “joins” manually by diving into the XSL.  When I started working with DVWPs, there wasn’t much available to tell me how to do things, so I just made it up based on what worked.

Today I saw this video from Laura Rogers that showed the way you are probably “supposed” to do a “join” in your DVWP.  Take a look.  I may have once followed this route, but it would have been long ago!

A few observations on all of this:

  • When you create a Linked Source, what actually happens is that the information about the sources is saved into an XML file in the _catalogs/fpdatasources Document Library in the current site.  What this XML file contains is information about the SharePoint:AggregateDataSource in a udc:DataSource wrapper.   Each time you use the Linked Source, this information is copied in as the SharePoint:AggregateDataSource for your DVWP.  Think of it as a SharePoint:AggregateDataSource template.  If you can make the CAML more efficient, and you expect to reuse the Linked Source, you can do it here.
  • Upon initial creation of the DVWP from the Linked Source, there are templates in the DVWP named dvt_1, dvt_1.body, and dvt_1.rowview.  (Depending upon the other options you choose from there, you may end up with more dvt_1.* templates.)
  • Note that both Data Sources (in this case; there can be many) have the selectcommand=”<View></View>” by default, so there is no efficiency in the “join”.  I haven’t seen issues with this, even with thousands of rows, but folks often [virtually] look at me askance when I suggest doing the filtering after the items have been retrieved.  (I often reply with “I learned to program in 16k of memory, so this makes me blanch, too, but I just haven’t seen performance problems.)  If you expect that you will have large numbers of items in your lists, think about how you can add WHERE clauses into your CAML to reduce the number of items retrieved initially as I mention above.
  • When you add the first Joined Subview, what happens is that a second set of templates called dvt_2, dvt_2.body, and dvt_2.rowview are created in your DVWP. This set of templates is for the second Data Source (thus the names).
  • The “join” isn’t really a join at all.  The dvt_1.rowview template calls the dvt_2 template and the values of the columns which you specify in the Joined Subview dialog are used to filter the second Data Source, something like this:
    <xsl:call-template name="dvt_2">       
    <xsl:variable name="dvt_ParentRow" select="current()" />         
    <xsl:variable name="Rows" select="../../../Assignees/Rows/Row&#91;@Title=$dvt_ParentRow/@Title&#93;" />

You can watch all of these things happen if you follow along with Laura’s video and do the same things that she is doing in Split mode in SharePoint Designer.  At this point, you’re sort of where I end up when I do most of this manually.  However, there are some best practices which I follow which I thought I’d pass along:

  • Rename the templates from dvt_1.* and dvt_2.* to match your list names.  So, given the code above, I’d rename dvt_2 to Assignees, dvt_2.body to Assignees.body, and dvt_2.rowview to Assignees.rowview.  This makes following even your own code much easier, and it certainly ought to make more sense to someone else who gets stuck with it.
  • Rather than using the dvt_ParentRow logic above, call the dvt_2 template (which is called something like Assignees now, right?) with the columns you want to “join” on as parameters, something like this:
    <xsl:call-template name="dvt_2">       
        <xsl:with-param name="Title" select="@Title"/>        
    </xsl:call-template>

    and then the top of your dvt_2 template looks like this:

    <xsl:template name="dvt_2">        
      <xsl:param name="Title""/>        
      <xsl:variable name="Rows" select="../../../Assignees/Rows/Row&#91;@Title=$Title&#93;" /> 
  • This way, if you need to “join” (notice how I keep putting “join” in quotes) based on multiple columns or a calculation, you’re positioned for it.  Simply pass in the additional parameter(s) and add the logic to the filter in dvt_2.

Once you’re as familiar with DVWPs as I am, you may forego the dialogs, too, but hopefully this gives you some better ideas about what’s going on “under the hood”.

Similar Posts

65 Comments

  1. Hi, i am unable to watch the Laura video, please can u check the videoURL and if it has changed post the new URL

  2. Hello Marc,

    Is it possible to merge result set of three different folders into one variable and use that variable in rendering of HTML?

    I have one scenario like:
    1. I have one custom list “MyList” (With 4-5 columns)
    2. I have 2 folders within this list.
    3. Structure is like:
    MyList (Listname)
    —- Folder1
    Have some data
    —- Folder2
    Have some data
    4. I am rendering html using page layout (Using data form web part and xslt)
    5. I am writing queries on both the folders as below:

    6. I am getting two result set in these variables.
    7. I want to merge these two variables values into (Var3) one variable as single result set and utilize that variable to render html.

    Can you provide your input on this.

    Thanks,
    Kirti

  3. Mark,

    I have 3 more folders which is not including in the query (not rendering any data from these 3 folders).
    So i have total 5 folders. I am using only two folders from this and want to merge data of two folders only.
    I have used scope=Recursive in my select statement and used following queries on two different folders:

    I want to merge results of this two variables into one and want to use that variable as final out put and utilize in HTML rendering.

    Let me know you thoughts on this.

    Thanks,
    Kirti

    1. @Kirti:

      Probably the easiest way to do this is to add a filter that only returns those two folders based on their name or path. If there were some other piece of metadata on the two folders, you could also filter on that. In other words: one query with a filter rather than multiple queries.

      M.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.