Comparing each items to remaining items of a list - list

I am trying to compare each table column with other table's column one by one.
Here is the scenerio
I have three tables like this
and I am getting their information like this as List of TableRow
TableRow(students,INT,10,id)
TableRow(students,VARCHAR,200,name)
TableRow(students,VARCHAR,100,address)
TableRow(department,INT,10,id)
TableRow(department,VARCHAR,100,department_name)
TableRow(teacher,INT,10,id)
TableRow(teacher,INT,10,suvject)
suppose I want to compare each row to remaining rows of other tables like this ->
TableRow(students,INT,10,id) - TableRow(department,INT,10,id)
TableRow(students,INT,10,id) - TableRow(department,VARCHAR,100,department_name)
TableRow(students,INT,10,id) - TableRow(teacher,INT,10,id)
TableRow(students,INT,10,id) - TableRow(teacher,INT,10,suvject)
TableRow(students,VARCHAR,200,name) - TableRow(department,INT,10,id)
TableRow(students,VARCHAR,200,name) - TableRow(department,VARCHAR,100,department_name)
TableRow(students,VARCHAR,200,name) - TableRow(teacher,INT,10,id)
TableRow(students,VARCHAR,200,name) - TableRow(teacher,INT,10,suvject)
TableRow(students,VARCHAR,100,address) - TableRow(department,INT,10,id)
TableRow(students,VARCHAR,100,address) - TableRow(department,VARCHAR,100,department_name)
TableRow(students,VARCHAR,100,address) - TableRow(teacher,INT,10,id)
TableRow(students,VARCHAR,100,address) - TableRow(teacher,INT,10,suvject)
TableRow(department,INT,10,id) - TableRow(teacher,INT,10,id)
TableRow(department,INT,10,id) - TableRow(teacher,INT,10,subject)
TableRow(department,VARCHAR,100,department_name) - TableRow(teacher,INT,10,id)
TableRow(department,VARCHAR,100,department_name) - TableRow(teacher,INT,10,subject)
Therefore I am comparing each tables column to other table's column like above..
I am using code like this to compare it, which works but is there any better approach for doing this ? A good functional way of writing it ?
val stack = mutable.Stack[TableRow]().pushAll(tableRows)
val arrayList = new util.ArrayList[JoinInfo]()
while (stack.nonEmpty) {
val currentRow = stack.pop()
stack.foreach(targetRow => {
if (!(targetRow.tableName.equals(currentRow.tableName) && targetRow.schema.equals(currentRow.schema))) { //not comparing with current table's column with its other column.
arrayList.add(compareColumns(currentRow, targetRow))
}
})
}

I would write something like this :
(tableRows zip tableRows).filter {
case(currentRow, targetRow) => !(targetRow.tableName.equals(currentRow.tableName) && targetRow.schema.equals(currentRow.schema))
}
So, pretty the same thing except it used the zip function to avoid manually writing the double loop.

Related

EXPAND MULTIPLE COLUMNS POWER BI

I´ve been struggling with this:
My table shows 3 records but when expanding there are like 100 columns. I used this code:
#"Expanded Data" = Table.ExpandTableColumn(#"Source", "Document", List.Union(List.Transform(#"Source"[Document]), each Table.ColumnNames(_))),
but it's not working. How can I expand simultaneously all columns? Also, inside those columns there are even more, for example I expand the first time end then those new columns have more records inside.
What could I do? Thanks in advance!
Try this ExpandAllRecords function - it recursively expands every Record-type column:
https://gist.github.com/Mike-Honey/0a252edf66c3c486b69b
This should work for Records Columns.
let
ExpandIt = (TableToExpand as table, optional ColumnName as text) =>
let
ListAllColumns = Table.ColumnNames(TableToExpand),
ColumnsTotal = Table.ColumnCount(TableToExpand),
CurrentColumnIndex = if (ColumnName = null) then 0 else List.PositionOf(ListAllColumns, ColumnName),
CurrentColumnName = ListAllColumns{CurrentColumnIndex},
CurrentColumnContent = Table.Column(TableToExpand, CurrentColumnName),
IsExpandable = if List.IsEmpty(List.Distinct(List.Select(CurrentColumnContent, each _ is record))) then false else true,
FieldsToExpand = if IsExpandable then Record.FieldNames(List.First(List.Select(CurrentColumnContent, each _ is record))) else {},
ColumnNewNames = List.Transform(FieldsToExpand, each CurrentColumnName &"."& _),
ExpandedTable = if IsExpandable then Table.ExpandRecordColumn(TableToExpand, CurrentColumnName, FieldsToExpand, ColumnNewNames) else TableToExpand,
NextColumnIndex = CurrentColumnIndex+1,
NextColumnName = ListAllColumns{NextColumnIndex},
OutputTable = if NextColumnIndex > ColumnsTotal-1 then ExpandedTable else #fx_ExpandIt(ExpandedTable, NextColumnName)
in
OutputTable
in
ExpandIt
This basically takes Table to Transform as the main argument,and then one by one checks if the Column Record is expandable (if column has "records" in it, it will expand it, otherwise move to next column and checks it again).
Then it returns the Output table once everything is expanded.
This function is calling the function from inside for each iteration.

LOOP to Look up the value in M Query

I have a following data table:
I need to create a column called FINAL VALUE with certain rules in the power query editor:
The FINAL VALUE is created based on the COUNTRY
If VALUE is greater than 100, then the previous value will be taken
if the previous values (no previous value such as 202001) are all greater than 100, then 100
So the final table should look like:
I sort COUNTRY and DATE, and then I try to apply loop in M Query. As I am not familiar with the function in M query, I have hard time figuring out. I appreciate any help. Thank you.
I believe you are better of in DAX. You can create a new column like below:
Final Value =
var curCountry = TableCountry[Country]
var curDate = TableCountry[Date]
var prevDate = CALCULATE(MAX(TableCountry[Date]), FILTER(TableCountry, curDate >= TableCountry[Date] && curCountry = TableCountry[Country] && TableCountry[Value] <=100))
return LOOKUPVALUE(TableCountry[Value], TableCountry[Country], curCountry, TableCountry[Date], prevDate, 100)

IF Formula in Power BI DAX

I would like to do a nested if statement within powerbi, I need to have multiple if statements in one column with some returning - value depending on the if statement.
I have tried to below however theyre all coming back as false.
Calculated value = if('TableName'[ColumnName1] = "exp1" && 'TableName'[columnName2] = "exp2", 'TableName'[value]|| if('TableName'[ColumnName1] = "exp1" && 'TableName'[ColumnName2] = "exp3", - 'TableName'[value],""))
In the first if you don't have any output to the false result. I Add an extra empty value in your calculated value as below only to exemplify what you need to add:
Calculated value = if('TableName'[ColumnName1] = "exp1" && 'TableName'[columnName2] = "exp2", 'TableName'[value]|| if('TableName'[ColumnName1] = "exp1" && 'TableName'[ColumnName2] = "exp3", - 'TableName'[value],""),"")
Check the example and tell something about this, please

Is it possible to create an inner join between two tables showing all B that contain A?

I have two tables: Kanji, and Vocabulary. Imagine the kanji table looks like this:
目
一
人
And the vocabulary table looks like this:
目的
一番目
一人
二人
人々
注目
目標
一匹
I want to generate a table that finds all vocabulary which contains the kanji in the kanji table and list them together. So the end result would look like this:
人 一人
二人
人々
一 一人
一番目
一匹
目 目的
一番目
注目
目標
I'm not sure how to go about this. If I have just one kanji, I can use the QUERY function to generate all of the vocabularies which contain that one kanji. But can I create a dynamic table which essentially inner joins the "kanji" and "vocabulary" tables, looking for every instance of "vocabulary" contains "kanji"?
I tried using a QUERY to combine the two tables, but it won't work because the tables are mismatched in size:
=QUERY({C1:C296,D1:D224}, "SELECT Col2 WHERE Col1 contains Col2")
In the above example, the C column / Col2 is vocabulary, the D column / Col1 is kanji.
Is there a way to do this using Google Sheets?
The simplest workaround is to get intersections by 1 value:
=FILTER(D:D;REGEXMATCH(D:D;"目"))
The picture shows how to use the copy of this function to get all intersections
The other approach is to use big array-formula like:
=TRANSPOSE(SPLIT(TEXTJOIN(",";1;TRANSPOSE(ARRAYFORMULA(IF(REGEXMATCH(A1:A8;TRANSPOSE(B1:B3));A1:A8;))));","))
=ARRAYFORMULA(SORT(TRIM(SPLIT(TRANSPOSE(SPLIT(QUERY(TRANSPOSE(QUERY(TRANSPOSE(
IF(IFERROR(REGEXEXTRACT(IFERROR(REGEXEXTRACT(C1:C, REPT("(.)", LEN(C1:C)))),
TEXTJOIN("|", 1, A1:A)))<>"", "♦"&IFERROR(REGEXEXTRACT(IFERROR(
REGEXEXTRACT(C1:C, REPT("(.)", LEN(C1:C)))), TEXTJOIN("|", 1, A1:A)))&"♣"&C1:C, ))
,,999^99)),,999^99), "♦")), "♣"))))
seriously, much better way, just add a custom function:
/**
* inner join on equality
*
* #param {Range} items1 Table 1
* #param {Range} items2 Table 2
* #param {Integer} ix1 0-based index of key in Table1
* #param {Integer} ix2 0-based index of key in Table2
*
* #customfunction
* #author marc meyer (marqueymarc)
*/
function innerJoinEQ(items1 = [[]], items2 = [[]], ix1= 0, ix2= 0) {
var res = [];
var item2ix = 0;
var map = new Map();
items1 = Array.isArray(items1)? items1: [[items1]];
items2 = Array.isArray(items2)? items2: [[items2]];
items2.forEach((item2) => {
let entries = map.get(item2[ix2]) || [];
entries.push(item2);
map.set(item2[ix2], entries);
});
items1.forEach((item1) => {
let entries = map.get(item1[ix1]) || [];
entries.forEach((rightPart) => {
let cp = rightPart.slice();
cp.splice(ix2, 1);
res.push([...item1, ...cp]);
})
});
return res;
}

Coldfusion/Lucee - Loop over 3D array to insert into database using multiple inserts using one query

I know the title is a mouth-full - sorry about that but trying to be specific here.
DB: MySql (technically Maria)
ColdFusion (technically Lucee: 5.x)
The array looks like the following:
NOTE: the outter most array only shows part of 2 and could continue through into the 30's.
I'm looking to perform a loop over the array to insert the elements marked as "string" in the image into the database using one query. Query has been trimmed for the sake of clarity and conciseness:
for (outer = 1; outer <= ArrayLen(myArray); outer++) {
local.currentrow = local.currentrow + 1;
for (inner = 1; inner <= ArrayLen(myArray[outer]); inner++) {
local.sql = "
INSERT INTO table (uuid, typeID, menuId, activityID, userID)
VALUES (
'#local.uuid#',
#myArray[outer][inner][1]#,
#myArray[outer][inner][2]#,
#myArray[outer][inner][3]#,
#arguments.formDataStruct.userID#
)";
queryExecute(local.sql);
}
}
I'm looking for something along this line but as written, it isn't working:
local.sql = "
INSERT INTO table (uuid, typeID, menuId, activityID, userID)
VALUES (
if (local.currentrow gt 1) {
,
}
for (outer = 1; outer <= ArrayLen(myArray); outer++) {
local.currentrow = local.currentrow + 1;
for (inner = 1; inner <= ArrayLen(myArray[outer]); inner++) {
'#local.uuid#',
'#myArray[outer][inner][1]#',
'#myArray[outer][inner][2]#',
'#myArray[outer][inner][3]#',
'#arguments.formDataStruct.userID#'
}
})
";
queryExecute(local.sql);
The error message I'm getting is
Element at position [1] doesn't exist in array
but if I perform a writedump[1][3][3] (e.g.), I'll get the value 24.
I would recommend against looping over an INSERT statement and rather just loop over VALUES to generate a single INSERT statement. A single INSERT will perform significantly faster, plus it will minimize the connections to your database.
Build out the list of values with something like:
for (var outer in arguments.inArray) {
for (var inner in outer) {
// Concat elements of inner array to a SQL VALUE string. If UUID is supposed to be a unique identity for the row, use Maria's uuid() instead of CF (or skip the UUID insert and let Maria do it).
// inArray elements and inUserID should be sanitized.
local.values &= "( uuid(), '" & inner[1] & "','" & inner[2] & "','" & inner[3] & "'," & local.userID & ")," ;
}
}
local.values = left(local.values,len(local.values)-1) ; // Get rid of the last comma.
local.sql = "INSERT INTO table (uuid, typeID, menuId, activityID, userID) VALUES " & local.values ;
After you've built up the SQL INSERT string, execute the query to INSERT the records. (You would probably build the above function differently to handle building the query string and parameters and then executing it all in one place.)
Don't forget to sanitize your array and other inputs. Does the array come from a source you control or is it user input?
https://trycf.com/gist/7ad6af1e84906b601834b0cc5ff5a392/lucee5?theme=monokai
http://dbfiddle.uk/?rdbms=mariadb_10.2&fiddle=d11f45f30723ba910c58a1e3f7a7c30b