简体   繁体   中英

Query 2 tables and combine data in a single array

I am trying to combine the results from 2 queries into a single array but am having problems getting the correct code.

I have a table called PrimaryEvents that I query to add to an array. This query works ok:

    $rows = query("SELECT * FROM PrimaryEvents WHERE unit = ? ORDER BY event", $unit);

I add the data to an array using the following:

    foreach ($rows as $row)
        {
        //    $event = lookup($row["event"]); (removed as spotted by sergio not required)
            $event["event"] = $row["event"];
            $event["validity"] = $row["validity"];
            $event["eventsrequired"] = $row["eventsrequired"];
            $event["unit"] = $row["unit"];
            $event["role"] = $row["role"];

            //now we have the data lets try and do something to it
            if ($event["role"] == "0")
                {
                    //then the user is active so change value to a YES
                    $event["role"] = "ALL";
                }

            //add our stock to the portfolio array
            $portfolio[] = $event;  
        }

So far everything works well. I would like to query a separate table and add certain results to the array portfolio[];

    $rowsCompleted = query("SELECT * FROM portfolio WHERE id = ? ORDER BY name", $_SESSION["id"]);

My original plan was to use the following additional code to add the data of interest to the portfolio[] but it doesn't work:

    //now add individual stats to the array
    foreach($rowsCompleted as $row)
    {
        if ($portfolio["event"] == $row["name"]
        {
        //then add our number and date to the array
        $portfolio["datecompleted"] = $row["datecompleted"];
        $portfolio["number"] = $row["number"];
        }

    //else do nothing
    }

My final aim was to pull the datacompleted value and number value from the portfolio table and then add it to the array ONLY if the event name matches the name in portfolio array.

Hopefully I have described my problem and required behaviour well enough.

Thanks for nay help that can be offered, I am new to php/sql so learning as I go.

Andy

EDIT: Also tried the following loop to try and loop through the array:

    //now add individual stats to the array
    foreach($rowsCompleted as $row)
    {
        foreach ($portfolio["event"] as $item)
        {
        if ($portfolio["event"] == $row["name"]
        {
            //then add our number and date to the array
            $portfolio["datecompleted"] = $row["datecompleted"];
            $portfolio["number"] = $row["number"];
        }
        }
    //else do nothing
    }

EDIT2: To try and make my question more clear: The Primary-events table lists all the events a specific user has to complete. The portfolio table tracks which events have been completed by the user (by means of date-completed and number).

I want to run a query that lists all the events from Primary-events, then into those results add the date-completed and number from the users portfolio. If the answer is blank from the portfolio then the user has not yet completed the event but I would still like to list it from the Primary-events table data.

I tried 2 queries to start with as it seemed to follow what I was trying to achieve.

EDIT3 :

New code with help from Barmar

    foreach ($rows as $row) {
        $event = lookup($row["event"]);
        $event["event"] = $row["event"];
        $event["validity"] = $row["validity"];
    //  $event["datecompleted"] = $row["datecompleted"];
    //  $event["number"] = $row["number"];
        $event["eventsrequired"] = $row["eventsrequired"];
        $event["unit"] = $row["unit"];
        $event["role"] = $row["role"];

    //now we have the data lets try and do something to it
        if ($event["role"] == "0") {
    //then the user is active so change value to a YES
            $event["role"] = "ALL";
        }

    //add our stock to the portfolio array
        $portfolio[] = $event;

    //now add individual stats to the array
        foreach ($rowsCompleted as $row) {
            foreach ($portfolio as &$item) {
                if ($item["event"] == $row["name"]) {
    //then add our number and date to the array
                    $item["datecompleted"] = $row["datecompleted"];
                    $item["number"] = $row["number"];
                }
            }
        }

    }

The page still isn't being displayed by chrome so guessing i've missed something.

EDIT4 : Page displayed, I am now getting undefined index errors when the table is rendered on the html page.

Specifically the undefined index errors are for date-completed and number. I am taking it to mean that these values are not being added to the portfolio array? Do try and help I have added an Else statement (as below) to ensure that even if the event isn't available the index is:

    //now add individual stats to the array
    foreach($rowsCompleted as $row)
    {
        foreach ($portfolio as &$item)
        {
             if ($item["event"] == $row["name"])
             {
        //then add our number and date to the array
            $item["datecompleted"] = $row["datecompleted"];
            $item["number"] = $row["number"];
             }
            else 
            {
            $item["datecompleted"] = "Never";
            $item["number"] = "0";
            }
        }
    }

EDIT 5: Near Success. Sorry to reopen this but I have just noticed behaviour I wasn't expecting: The nested loop only sets the date-completed and number for the first value to matches from the portfolio table. The follow on values are not set. It would seem like the nested loop isn't stepping through all of the portfolio values, and just exiting once the first "event" == "name".

EDIT 6: Sample data and clarification on desired functions:

portfolio sample data

    |id|name    |number|datacompleted
    |21|event1  |3     |2014-07-07
    |15|event1  |5     |2014-07-05
    |21|event2  |5     |2014-05-08
    |15|event1  |1     |2013-05-05

id is the id of the user that completed the event number is the number of events completed

PrimaryEvents sample data

    |id|event   |validity|eventsrequired
    |1 |event1  |7       |10
    |1 |event2  |25      |1
    |1 |event3  |12      |50

id is the id of the user that created the entry (used for historic purpose only)

The desired functionality is:

The query should create a an array to allow a html table to be created of everything within the Primary-events table. This table lists the events the user must complete.

The second query or current nested loop should gather the data from the portfolio table for the current user id, then match the event name to the name in the Primary-events array and update (if present) the number and date-completed value. (IE populate the data for the events that the user has completed).

The current code merges the data from portfolio only for the first match, but then the nested loop seems to exit.

Hopefully this is a more clear description of what I am trying to achieve.

EDIT: I have changed the functionality to use the Left join statement below but am still having problems:

The table only contains some of the events from primary-events table and not all of them. The events being pulled over are only those that the user has completed, the ones the user has not yet completed are not being shown.

EDIT: This query seems to work:

    $allEvents = query("SELECT * FROM PrimaryEvents LEFT JOIN portfolio ON (PrimaryEvents.event = portfolio.name) WHERE PrimaryEvents.event = ? AND (portfolio.id = ? Or portfolio.id is null) ORDER BY PrimaryEvents.event", $currentEvent, $_SESSION["id"]);

You need to notice that portfolio is not associative array but multidimensional array, so you cannot access it using $portfolio["event"] . You should use $portfolio[0]["event"] , $portfolio[1]["event"] and so on.

It's hard to show you exact solution because I don't know how those arrays/database queries should be merged.

EDIT

It seems your query should look like this:

query("SELECT * FROM PrimaryEvents e LEFT JOIN portfolio p ON e.event = p.name WHERE e.unit = ? AND p.id = ? ORDER BY e.event", $unit,$_SESSION["id"]);

EDIT2

I haven't proposed nested loop (as it's now in modified question) because of performance loss.

You're getting closer with your second query, but still confused about what's in each array.

foreach($rowsCompleted as $row)
{
    foreach ($portfolio as &$item) // Need to use reference so we can update it
    {
        if ($item["event"] == $row["name"])
        {
            //then add our number and date to the array
            $item["datecompleted"] = $row["datecompleted"];
            $item["number"] = $row["number"];
            break;
        }
    }
}

To avoid the nested loop, it would be better for $portfolio to be an associative array. Change the code for your initial query to use:

    //add our stock to the portfolio array
    $portfolio[$event["name"]] = $event;  

Then the second loop becomes:

foreach($rowsCompleted as $row)
{
    $name = $row["name"];
    if (isset($portfolio[$name]) {
        $portfolio[$name]["datecompleted"] = $row["datecompleted"];
        $portfolio[$name]["number"] = $row["number"];
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM