postgresql, select multiple json_array_elements works so werid - json

I want use json_array_elements to expands json array. But it works so werid. Pls see below.
select json_array_elements('[1, 2]') as a, json_array_elements('[2, 3, 4]') as b;
a | b
---+---
1 | 2
2 | 3
1 | 4
2 | 2
1 | 3
2 | 4
(6 rows)
select json_array_elements('[1, 2]') as a, json_array_elements('[2, 3]') as b;
a | b
---+---
1 | 2
2 | 3
(2 rows)
It's seems when the length of the arrays are equal, something goes wrong.
Can anyone tell me, why is like this.

PostgreSQL repeats each list until both happen to be at the end simultaneously.
In other words, the length of the result list is the least common multiple of the length of the input lists.
This behaviour is indeed weird, and will be changed in PostgreSQL v10:
select json_array_elements('[1, 2]') as a, json_array_elements('[2, 3, 4]') as b;
a | b
---+---
1 | 2
2 | 3
| 4
(3 rows)
From the commit message:
While moving SRF evaluation to ProjectSet would allow to retain the old
"least common multiple" behavior when multiple SRFs are present in one
targetlist (i.e. continue returning rows until all SRFs are at the end of
their input at the same time), we decided to instead only return rows till
all SRFs are exhausted, returning NULL for already exhausted ones. We
deemed the previous behavior to be too confusing, unexpected and actually
not particularly useful.

Related

Mysql: Find most similar numerical rows based on multiple columns

This is my first question here, I'll try my best to be clear and factual. I've googled for quite a long time but never got the result I wanted. My Mysql knowledge isn't the best and maybe that's why I can't get this answer to work with my wanted function.
At first, here's my Mysql data
user | speed | strength | stamina | precision
---------------------------------------------
1 | 4 | 3 | 5 | 2
2 | 2 | 5 | 3 | 4
3 | 3 | 4 | 6 | 3
Question
I want a Mysql query that find the most similar row to a specific user. For example, if I want to see who's most similar to user 1, I want it to find user 3. User 1 and 2 have in total the same value (14) but 1 and 3 are more similar, see the picture for a better view.
I'd be so glad and grateful if someone knew what Mysql function I should look at, or if you have any ideas.
I think your requirement translated into functions would be "the minimum value of the average of the differences between users scores at ability level".
If that's the case, it can be translated in SQL like this
select t2.user,
(
abs(t1.speed - t2.speed) +
abs(t1.strength - t2.strength) +
abs(t1.stamina - t2.stamina) +
abs(t1.precision - t2.precision)
) / 4 as diff_avg
from users t1
cross join
users t2
where t2.user <> t1.user and
t1.user = 1 /* the starting user id goes here */
order by 2 asc
limit 1
The most accurate solution to do this numerically is by using profile similarity - by getting the rows with the highest correlation coefficient to User1
I have been looking for a way to do this in MySQL but can't seem to find a way to. Hope someone knows enough about this to help us

Rendering image field in SSRS to fill the page [duplicate]

I am trying to achieve the following layout for my report based on one query.
+----+-------+----+-------+
| ID | Name | ID | Name |
+----+-------+----+-------+
| 1 | Danny | 2 | Dave |
| 3 | Sue | 4 | Jack |
| 5 | Rita | 6 | Sarah |
+----+-------+----+-------+
So I basically want one table, printing my data from left to right to save space on my page, rather than it printing one line and wasting all of the space on the right side of the paper, possibly even go 3 times across the width.
This is my data: http://sqlfiddle.com/#!3/5c911/1
I was maybe thinking a table with 4 columns. Cols 1 and 2 contain the odd row numbers, Cols 3 and 4 contain the even row numbers.
How could I achieve this, I did try something with the MOD function but it didn't seem to work properly, or I misunderstood what was happening.
Related:
How can I display two rows worth of data on one line side-by-side in Report Designer?
Thanks,
To print your data from left to right in a multi-column format, you need to fake it using multiple tables. To implement this hack, create the same number of tables as columns you want side by side that all point to your data set. On the Detail row of the first table, for the Visibility-Hidden property use the following formula:
=IIF((RowNumber(Nothing) Mod 4) = 1, False, True)
where 4 is the number of tables (columns) you have.
Do the same for each table, incrementing what the formula is equal to (so for the second column (RowNumber(Nothing) Mod 4) = 2 and so forth). In the last table (column) the formula equals 0.
This alternately hides the detail row, only displaying the appropriate rows for that column number.
You can achieve that look with query.
SELECT std1.id AS Student_Id,
std1.NAME AS Student_Name,
std2.id AS Student_Id,
std2.NAME AS Student_Name
FROM students std1, students std2
WHERE (std2.id - std1.id = 1
AND std1.id %2 = 1);

MySQL Reciprocal Search

I have a table which stores the edges of a directed graph like so:
Table EDGES
FROM_NODE | TO_NODE | STRENGTH
1 | 1 | 8
1 | 2 | 5
2 | 1 | 4
1 | 3 | 2
3 | 4 | 1
And I'm trying to search for edges which are supported in both directions with strength > 3. In the example above, 1 -> 2 and 2 -> 1 both exist, however, 1 <-> 3 does not exist in both directions. 1 -> 1 doesn't count, for obvious reasons.
The major complication is that there are over 1,000,000 edges to search, and all the queries I have tried so far fail before I can check if they've worked.
Any suggestions would be greatly appreciated!
To me the most straightforward solution is something like:
select one.from_node, one.to_node
from edges one
join edges other on (one.to_node = other.from_node AND one.from_node = other.to_node)
where one.strength > 3 AND other.strength > 3
AND one.from_node <> one.to_node
If you have a lot of data, than it's might be a good idea to reconsider indexes on the table and raise the execution limit.
Here is an sql fiddle to check the query.
I think you can use something like this:
select
least(FROM_NODE, TO_NODE) as n1,
greatest(FROM_NODE, TO_NODE) as n2
from
edges
where FROM_NODE<>TO_NODE and nodes.strength>3
group by n1, n2
having count(*)=2

SSRS report formatting a table to display data side by side

I am trying to achieve the following layout for my report based on one query.
+----+-------+----+-------+
| ID | Name | ID | Name |
+----+-------+----+-------+
| 1 | Danny | 2 | Dave |
| 3 | Sue | 4 | Jack |
| 5 | Rita | 6 | Sarah |
+----+-------+----+-------+
So I basically want one table, printing my data from left to right to save space on my page, rather than it printing one line and wasting all of the space on the right side of the paper, possibly even go 3 times across the width.
This is my data: http://sqlfiddle.com/#!3/5c911/1
I was maybe thinking a table with 4 columns. Cols 1 and 2 contain the odd row numbers, Cols 3 and 4 contain the even row numbers.
How could I achieve this, I did try something with the MOD function but it didn't seem to work properly, or I misunderstood what was happening.
Related:
How can I display two rows worth of data on one line side-by-side in Report Designer?
Thanks,
To print your data from left to right in a multi-column format, you need to fake it using multiple tables. To implement this hack, create the same number of tables as columns you want side by side that all point to your data set. On the Detail row of the first table, for the Visibility-Hidden property use the following formula:
=IIF((RowNumber(Nothing) Mod 4) = 1, False, True)
where 4 is the number of tables (columns) you have.
Do the same for each table, incrementing what the formula is equal to (so for the second column (RowNumber(Nothing) Mod 4) = 2 and so forth). In the last table (column) the formula equals 0.
This alternately hides the detail row, only displaying the appropriate rows for that column number.
You can achieve that look with query.
SELECT std1.id AS Student_Id,
std1.NAME AS Student_Name,
std2.id AS Student_Id,
std2.NAME AS Student_Name
FROM students std1, students std2
WHERE (std2.id - std1.id = 1
AND std1.id %2 = 1);

Select from a table that uses materialized path to encode a tree, ordered by depth-first (no recursive/ltree)

I have a table in a relational database, in which I encode a tree using the technique known as Materialized path (also known as Lineage column). That is, for each node in my tree I have a row in the table, and for each row I have a string column named ancestry where I store the path from the root node to the node represented by this row.
Is it possible, and if yes - how, to select the rows in the table orderd by preorder, that is they should appear in the result set in the order that would result by visiting the tree depth-first. I use MySQL - so no recursive queries and no ltree extension.
For example, a tree, it's table, and selected ordered by preorder:
1 SELECT * FROM nodes SELECT * FROM nodes ORDER BY ?depth_first_visit_order?
| \ id | ancestry id | ancestry
2 3 ------------- -------------
| | \ 1 | NULL 1 | NULL NOTE: I don't care about the
4 5 6 2 | 1 2 | 1 order of siblings!
| 3 | 1 4 | 1/2
7 4 | 1/2 3 | 1
5 | 1/3 5 | 1/3
6 | 1/3 7 | 1/3/5
7 | 1/3/5 6 | 1/3
Note: I am interested explicitly in doing this over a materialized path encoding!
Related: What are the options for storing hierarchical data in a relational database?
I believe what you want is an alphabetic sort.
SELECT id, ancestry, ancestry + '/' + CAST(id as nvarchar(10)) AS PathEnumeration
FROM nodes
ORDER BY 3 ASC;
I don't really remember how MySQL concatenates, but I'm sure my meaning is clear.
1
1/2
1/2/4
1/3
1/3/5
1/3/5/7
1/3/6
Note that it is an alphabetic sort, so 11 will show up before 2. But, you said you didn't care about sibling ordering. I, of course, would rewrite it as a nested set ;)
this will order by the last number of your "ancestry"
select *,
Substring(ancestry,LEN(ancestry) - Charindex('/',Reverse(ancestry))+2, LEN(ancestry)) as END_CHAR
from nodes
order by END_CHAR desc
I didn't try with numbers bigger that 9, you may have to cast to int