Doctrine Hydrate joined Entities into one array-entry - doctrine-orm

I'm currently encountering some problems with Doctrine Hydration. I'm using ZF2 to build an API and therefore i need to build some queries that make use of joins.
For now they look somewhat like this:
$qb->select(array('r, a'))
->from('Release\Entity\Release', 'r')
->leftJoin(
'Artist\Entity\Artist', a',
\Doctrine\ORM\Query\Expr\Join::WITH, 'a.id = r.artist'
)
->orderBy('r.id', 'ASC');
So if i hydrate the Result with AbstractQuery::HYDRATE_ARRAY the result will be an extra array entry for each joined table/entity.
Array
(
[0] => Array
(
[id] => 1
[artist] => 1
[title] => A super nice Release
[digital_release] => DateTime Object
(
[date] => 2014-01-25 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[physical_release] => DateTime Object
(
[date] => 2014-01-25 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[1] => Array
(
[id] => 1
[first_name] => John
[last_name] => Doe
[artist_name] => JD and the Beat-Machines
[created_at] => DateTime Object
(
[date] => 2015-04-17 13:16:18.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[updated_at] => DateTime Object
(
[date] => 2015-04-17 13:16:18.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[2] => Array
(
[id] => 2
[artist] => 14
[title] => Some other nice album
[digital_release] => DateTime Object
(
[date] => 2014-02-01 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[physical_release] => DateTime Object
(
[date] => 2014-02-01 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[...]
)
As you can see the artist of the corresponding release [0] is stored into array-key [1].
If I finally print the result as new JsonModel($result) this doesn't seem a workable way to me.
What i want to achieve is some result like this
Array
(
[0] => Array
(
[id] => 1
[artist] => Array
(
[id] => 1
[first_name] => John
[last_name] => Doe
[artist_name] => JD and the Beat-Machines
[created_at] => DateTime Object
(
[date] => 2015-04-17 13:16:18.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[updated_at] => DateTime Object
(
[date] => 2015-04-17 13:16:18.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[title] => A super nice Release
[digital_release] => DateTime Object
(
[date] => 2014-01-25 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[physical_release] => DateTime Object
(
[date] => 2014-01-25 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[2] => Array
(
[id] => 2
[artist] => Array
(
[id] => 14
[...]
)
[title] => Some other nice album
[digital_release] => DateTime Object
(
[date] => 2014-02-01 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
[physical_release] => DateTime Object
(
[date] => 2014-02-01 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
)
[...]
)
Maybe someone has a helpful advice how to get such an output :)
I've already tried to use AbstractQuery::HYDRATE_SCALAR, which comes a bit closer to what i want, but the result of the joined table is not a sub-array of the joined column.
Thanks in advance for every helpful hint :)
regards

Your problem is your mapping it's not good i think you have not a relation between Release and Artist.
You have to set a relation OneToMany between Artist and Release. Like this :
On artist side
/**
* #ORM\OneToMany(targetEntity="Release\Entity\Release", mappedBy="artist")
*/
protected $release;
And Release side
/**
* #ORM\ManyToOne(targetEntity="Artist\Entity\Artist", inversedBy="release")
* #ORM\JoinColumn(name="artist", referencedColumnName="idArtist", onDelete="RESTRICT")
*/
protected $artist;
Don't forget to the Artist side to instanciate a collection like this :
public function __construct()
{
$this->release= new ArrayCollection();
}
with this use :
use Doctrine\Common\Collections\ArrayCollection;
With this you can set your release entity and set the artist whith an artist object. You'll have the result you want.
$release = new Release;
$artist = new Artist;
$release->setArtist($artist);
EDIT
When you have your data, you have to populate your entity with it.
If you have a Form, you have to use DoctrineHydrator to achieve this, your object will be correctly hydrated, from your form. This may need to dig into doctrine documentation ;)
If your data comes from anywhere else, you can populate your entity with your entity's setters.
For e.g :
$relaseEntity->setDate($data['date']); // Be carefull to Datetime object for this
$releaseEntity->setName($data['name']);
And goes on...

Related

Power BI: Is there a way to get the a value based on the MAX date?

I am trying to make a calculated column in Power BI to return the last Job Title held for the name listed based on the maximum/latest date.
Current Title = VAR MaxDate =CALCULATE (MAX('Terms FY23'[Employee History.Date])) VAR EEID = CALCULATE(MAX('Terms FY23'[Employee History.Employee]))RETURN CALCULATE(FIRSTNONBLANK(SELECTCOLUMNS(FILTER('Terms FY23','Terms FY23'[Employee History.Date] = MaxDate && 'Terms FY23'[Employee History.Employee] = EEID),"JobTitle",'Terms FY23'[Employee History.Title]),_MaxDate))
I tried this but it returned the same exact Job Title column.
Date Full Name Job Title
10/31/2022 John Adams Landscaper I
11/30/2022 John Adams Crew Leader
12/31/2022 John Adams Crew Leader
1/31/2023 John Adams Crew Leader
2/15/2023 John Adams Crew Leader
For you sample data this one works
Last Job Title =
VAR MAXDATE =
MAXX('Table', 'Table'[Date])
RETURN
CALCULATE(
MAX('Table'[Job Title]),
FILTER(
ALL('Table'),
'Table'[Date] = MAXDATE
)
)
In case you have more than one distinct name in the table can go via this
calculated table
Lookup Table =
SUMMARIZE(
'Table',
'Table'[Full Name],
"Last Job Titel", CALCULATE(
MIN('Table'[Job Title]),
'Table'[Date] = MAX('Table'[Date])
)
)
to end up with this calulated column
Last Job Title=
LOOKUPVALUE(
'Lookup Table'[Last Job Titel],
'Lookup Table'[Full Name], 'Table'[Full Name]
)
You can add a calculated column that does this directly using the new INDEX windowing function as a filter argument, that uses ALLEXCEPT on your table to provide the correct row context:
Last Title =
CALCULATE (
SELECTEDVALUE ( 'Terms FY23'[Employee History.Title] ),
INDEX (
1,
ALLEXCEPT ( 'Terms FY23', 'Terms FY23'[Employee History.Name] ),
ORDERBY ( [Employee History.Date], DESC )
)
)
This type of calculation would normally require to store the maximum date value first, and then solve for the title:
Last Title Old =
VAR _max_date =
CALCULATE (
MAX ( 'Terms FY23'[Employee History.Date] ),
ALLEXCEPT ( 'Terms FY23', 'Terms FY23'[Employee History.Name] )
)
RETURN
CALCULATE (
SELECTEDVALUE ( 'Terms FY23'[Employee History.Title] ),
ALLEXCEPT ( 'Terms FY23', 'Terms FY23'[Employee History.Name] ),
'Terms FY23'[Employee History.Date] = _max_date
)
NB! If you have two people in this table with the same name, you are out of luck. You would need a more robust way of handling employees, for example by using a unique employee ID instead of some arbitrary name.

Power bi - Getting the most recent value from another table

Hi I'm a beginner in Power bi
I have two tables
Table 1 has Dates, Unique IDs and Emails
Table 2 has list of Unique IDs same as the ones in table 1
Using DAX, I want to add a calculated column to the 2nd table to get the most recent email from table 1 based on the unique id and also avoid Email Values
Thank you.
with DAX measure - if both tables have a relationship
Measure1 =
CALCULATE (
MAX ( 'Table 1'[Email] ),
FILTER (
'Table 1',
'Table 1'[Date]
= CALCULATE (
MAX ( 'Table 1'[Date] ),
ALLEXCEPT ( 'Table 1', 'Table 1'[Unique_ID] )
)
)
)
with DAX calculated column - if both tables have a relationship
Column1 =
CALCULATE (
CALCULATE (
MAX ( 'Table 1'[Email] ),
FILTER (
'Table 1',
'Table 1'[Date]
= CALCULATE (
MAX ( 'Table 1'[Date] ),
ALLEXCEPT ( 'Table 1', 'Table 1'[Unique_ID] )
)
)
)
)
with DAX measure - if both tables have no relationship
Measure2 =
CALCULATE (
MAX ( 'Table 1'[Email] ),
FILTER (
'Table 1',
'Table 1'[Date]
= CALCULATE (
MAX ( 'Table 1'[Date] ),
ALLEXCEPT ( 'Table 1', 'Table 1'[Unique_ID] )
)
),
TREATAS ( VALUES ( 'Table 2'[Unique_ID] ), 'Table 1'[Unique_ID] )
)
with DAX calculated column - if both tables have no relationship
Column2 =
CALCULATE (
CALCULATE (
MAX ( 'Table 1'[Email] ),
FILTER (
'Table 1',
'Table 1'[Date]
= CALCULATE (
MAX ( 'Table 1'[Date] ),
ALLEXCEPT ( 'Table 1', 'Table 1'[Unique_ID] )
)
),
TREATAS ( VALUES ( 'Table 2'[Unique_ID] ), 'Table 1'[Unique_ID] )
)
)
Oh sorry I just realized you're already having a table2. Now I've split the answer in two party. New Column and New Table.
Creating NEW COLUMN
In this case you could try:
Most_Recent_Mail = SELECTCOLUMNS(TOPN(1,FILTER(table1, table1[Unique_ID] = table1[Unique_ID]), table1[Date]), "mail", Tabelle1[mail])
Creating NEW TABLE
I copied your table:
Now we can create a new table:
And use the following DAX code to fill this table:
New_Table = SUMMARIZE(table1,table1[Unique_ID], "Most_Recent_Mail",
CALCULATE(VALUES(table1[mail]), FILTER(all(table1), table1[Date] = max(table1[Date]))))
SUMMARIZE is like a group function.
With CALCULCATE you can create expressions in a filtered context.
With FILTER you can create a new context/subset.
ALL is ignoring all existing filters an returns the full dataset.
Result:
PS: Just to understand. If you only wanted the date, the formula would be much shorter
table2 = SUMMARIZE(table1,table1[Unique_ID], "Max_Date",
max(table1[Date]))
And if you would like to have both, you can add as much columns you want:
New_Table = SUMMARIZE(table1,table1[Unique_ID],
"Max_Date", max(table1[Date]),
"Most_Recent_Mail",
CALCULATE(VALUES(table1[mail]), FILTER(all(table1), table1[Date] = max(table1[Date]))))

Power BI / DAX show count of distinct values in column

I'd like to expand the solution on this page.
The original solution is given in Power query. But I'd like a DAX solution...
I've created a table from the fields Source and Preparer. If I want to see those sources where there is only one preparer what's is the best way to do it via DAX?
Like the Sources "MN", "RT" and "PO".
Source
Preparer
AB
June
AB
Jane
MN
June
SS
Kim
SS
Lee
SS
Jim
RT
Kim
PO
June
PO
June
RT
Kim
The outcome I'm looking for is like:
Source
Preparer
Number
MN
June
1
RT
Kim
1
PO
June
1
DAX that comes close looks like:
TableResult =
FILTER (
SUMMARIZECOLUMNS (
'Table'[Source],
"Number", DISTINCTCOUNT ( 'Table'[Preparer] )
),
[Number] = 1
)
This gives the source and the number, but not the Preparer....
Any ideas?
Please try this
newMeasure =
CALCULATE (
DISTINCTCOUNT ( 'Table 1'[Preparer] ),
FILTER (
GROUPBY ( 'Table 1', 'Table 1'[Source], 'Table 1'[Preparer] ),
CALCULATE (
DISTINCTCOUNT ( 'Table 1'[Preparer] ),
ALLEXCEPT ( 'Table 1', 'Table 1'[Source] )
) = 1
)
)

Why my Path function is for Parent-Child is not working (Power BI)?

I am getting a missing value error on the Path function in DAX. I know my Parent _ID columns only have few accounts. That because I only have few parent account with child relationship. 
Ultimately I want to show the Parent account with the child (with plus sing expansion)  and other accounts in the same list. 
I also found the Power Bi Community post using "IF, LOOKUP VALUE, var function". It just gave me a blank column. 
Any idea how should achieve my parent-child hierarchy? 
Thank you
The problem is in the order of columns in function. ParentID should be the second one.
https://dax.guide/path/
I didn't manage to get EXCEPT to work correctly.
Here is an example that uses NOT IN instead.
-- Create missing parents for PATH command
Missing assemblies =
CALCULATETABLE(
SUMMARIZE(
'Item',
'Item'[Item id],
'Item'[Description],
'Item'[Inventory],
"Assembly id", BLANK(),
"Can ship", 1,
"Quantity per", 1
),
FILTER( 'Item', NOT( 'Item'[Item id] IN ALL( 'BOM Component'[Component id] )))
)
Hierachical assemblies =
UNION(
SELECTCOLUMNS(
'BOM Component',
"Assembly id", 'BOM Component'[Assembly id],
"Can ship", 'BOM Component'[Can ship],
"Component description", 'BOM Component'[Component description],
"Component id", 'BOM Component'[Component id],
"Inventory", 'BOM Component'[Inventory],
"Quantity per", 'BOM Component'[Quantity per]
),
SELECTCOLUMNS(
'Missing assemblies',
"Assembly id", 'Missing assemblies'[Assembly id],
"Can ship", 'Missing assemblies'[Can ship],
"Component description", 'Missing assemblies'[Description],
"Component id", 'Missing assemblies'[Item id],
"Inventory", 'Missing assemblies'[Inventory],
"Quantity per", 'Missing assemblies'[Quantity per]
)
)

Create a measure to return latest value

I am trying to retrieve the latest job designation of each ID and transaction with blank field.
The current code that I am using for creating a new measure
Result =
var i = SELECTEDVALUE('SampleData'[ID])
var d =
maxx(
filter(
all('SampleData'),
'SampleData' [ID] = i
&& 'SampleData' [Job Designation] <> BLANK()
),
'SampleData' [TS]
)
var de =
maxx(
filter(
all('SampleData'),
'SampleData' [ID] = i
&& 'SampleData' [aTS] = d
),
'SampleData' [Job Designation]
)
return de
Please refer to my sample data below.
enter image description here
As you refer to the sample data, I have "Update" transaction which involves updating of company details only. Therefore, user need not provide ID. The query that I currently have will remove the ones with blank ID.
The desired outcome is to retrieve the latest job designation for each ID and return blank if ID is empty, but Company ID has data (i.e. 852 and 654).
Please help me out.
Thank you in advance.
If I understand you correct, you need this below measure for your purpose-
latest_designation =
MAXX(
TOPN(
1,
FILTER(
ALLSELECTED('SampleData'),
'SampleData' [Job Designation] <> BLANK()
),
'SampleData' [TS],
DESC
),
'SampleData' [Job Designation]
)
As you have slicer for selecting ID, you do not need filter table using Slicer Value insider the measure.
I have found the answer.
I didn’t select “Show items with no data”.