在RedbeanPHP中使用JSON对象数组查询表

时间:2018-12-12 19:50:23

标签: php mysql json redbean

在Redbean PHP中工作时,我很难查询单个字段中包含json对象数组的表,并生成报告。

我想获得一份报告,其中按类别列出所有员工的小计。我知道这应该很容易/很明显,但我只是没有正确地做到这一点。

我有一个数据库,其中包含:

table clients
with columns:(int) client_id, (string) client_name, (array of json) notes
notes is an array of json with 
(int) note_id, (int) note_category_id, (int) staff_id, (string) description, (memo) content, (date) note_date

table staff with columns (int) sid, (string) sname

table categories with columns (int) cat_id, (string) cat_name

所以在伪代码中(因为我仍在设法解决所有问题) 我需要运行一个查询,如:(括号内为参数)

R::getAll('Select * from Join (staff, categories, clients) 
On (staff.sid=clients.services.staff_id, categories.cat_id=clients.services.note_category_id)
Where (clients.services.note_date Between [startdate] and [enddate], 
  categories.cat_name IN [chosencateg], staff.sname IN [pickednames])
Orderby sname Asc, cat_name Asc, note_date Desc ');

报告输出格式:

Filters used: [picked filter choices if any]
-----------
[sname]
--  note category: [cat_name] 1
        [note_date] 1   [description] 1 [content] 1
        [note_date] 2   [description] 2 [content] 2
    note category 1 subtotal
--  note category: [cat_name] 2
        [note_date] 3   [description] 3 [content] 3
        [note_date] 4   [description] 4 [content] 4
    note category 2 subtotal
staff subtotal
[sname] 2 ...

我要问的是一个相当通用的表,因为我必须处理许多相似的表,也许看到查询模板将有助于我的理解。

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

redbean非常棒,而且-getAll只是在摸索,实际上根本就没有在使用redbean ... Read up on it here

这是一个让您入门的查询模板:

查询模板:

1)

R::getAll('Select * from Join (staff, categories, clients) 
On (staff.sid=clients.services.staff_id, categories.cat_id=clients.services.note_category_id)
Where (clients.services.note_date Between :startdate and :enddate, 
  categories.cat_name IN (:chosencateg), staff.sname IN (:pickednames))
Orderby sname Asc, cat_name Asc, note_date Desc ');

您还可以简单地使用:

2)

R::getAll('Select * from Join (staff, categories, clients) 
On (staff.sid=clients.services.staff_id, categories.cat_id=clients.services.note_category_id)
Where (clients.services.note_date Between ? and ?, 
  categories.cat_name IN (?), staff.sname IN (?))
Orderby sname Asc, cat_name Asc, note_date Desc ');

唯一的区别是查询模板1使用命名参数(因此,将查找传递给它的参数数组以包含一个具有与查询中相同的命名参数的关联数组)。而模板2仅需要一个参数数组,索引按?的顺序排列。标记出现在查询中。

无论如何...查询应返回表示行的列的关联数组。 var_dump看起来像这样:

Array
(
[client_id] => 1,
[client_name] => "joe",
[noes] => "[
           {note_id=1
           ,note_category_id=1
           ,staff_id=1
           ,description=blah blah
           ,content=blah blah blah blah
           ,content=some content for this note
           ,note_date=12/06/2018
           }
           ]"
[sid] => 100,
[sname] => "some staff name"
[cat_id] => 100
[cat_name] => "some category name"
)

注意notes字段是如何以字符串形式出现的(我知道上面的json格式不正确,我只是想展示一个例子)。

我假设您想要的是将字符串转换为数组,以便您可以像处理数据而不是字符串那样使用它。因此,下面的内容应该可以帮助您开始:

一旦将其从数据库中取出,您应该可以像这样访问它:

$result = R::getAll($query,
['startdate'=> $mystartDate
,'enddate' => $myEndDate
,'chosencateg'=>$myChosenCategory
,'pickednames'=>$myPickedNames
]);
// this would output the json string to your screen
echo $result['notes'];

但是您似乎想像使用json一样,将其视为数据的一部分-因此...您需要先对其进行解码。

// decode my notes field:
foreach(array_key($result) as $key) {
/* you are working with a multidimensional array in this loop
, use $key to access the row index. Each row index 
will contain named column indexes that are column names from the database
*/
$result[$key]['decoded_notes'] = json_decode($result[$key]['notes'],true);
}
// I now have a new column in each row index, containing 'notes' 

作为另一个关联数组

// the statement below now results in an array to string conversion error:
echo $result[someIndexNumber]['decoded_notes'];

答案 1 :(得分:0)

因此,我决定在MySQL(5.7)中使用该功能。为此,我使用了字符串操作。 MySQL 8增加了json_table函数,这些函数本来很好。

我将每个JSON注释数组转换为“ INSERT INTO temptable”行,以将数组列表转换为模板行, 每行一个JSON对象,将client_id添加到每个对象,然后 执行这些语句。

SET @allnotes = (
SELECT json_arrayagg(REPLACE(`notes`,'{', CONCAT('{"id_client": ', id_client, ', ')))   /* add id_client to each note object */
FROM clients
WHERE `notes` != '' AND `notes` != '[]' );                      /* no empty note cases */
SET @allnotes = REPLACE(REPLACE(@allnotes ,'"[',''),']"','' );      /* flatten out outer array of each note */
SET @allnotes = REPLACE(REPLACE(@allnotes ,'{','("{'),'}','}")' );  /* INSERT INTO string formatting for the objects */

DROP TEMPORARY TABLE IF EXISTS jsonTemporary;
CREATE TEMPORARY TABLE IF NOT EXISTS jsonTemporary (anote json);
SET @allnotes = REPLACE(REPLACE(@allnotes,'[','INSERT INTO jsonTemporary (anote) VALUES '),']',';');

PREPARE astatement FROM @allnotes;
EXECUTE astatement;

/* totals */
SELECT concat(staff.last_name,", ",staff.first_name) AS sname,
categories.name AS cat_name,
count(anote->'$.id_client') AS cat_total,
FROM jsonTemporary
JOIN categories ON cast(anote->'$.note_category_id' as unsigned)=categories.id
JOIN clients ON clients.id_client=anote->'$.id_client'
JOIN staff ON staff.id=anote->'$.staff_id'
WHERE anote->'$.note_date' >= "2018-10-01" AND anote->'$.note_date' <= "2018-12-31"
GROUP BY sname, cat_name;

/* all notes */
SELECT concat(staff.last_name,", ",staff.first_name) AS sname,
categories.name AS cat_name,
anote->'$.note_date' AS n_date,
anote->'$.description' AS description,
anote->'$.content' AS content,
FROM jsonTemporary
JOIN categories ON cast(anote->'$.note_category_id' as unsigned)=categories.id
JOIN clients ON clients.id_client=anote->'$.id_client'
JOIN staff ON staff.id=anote->'$.staff_id'
WHERE anote->'$.note_date' >= "2018-10-01" AND anote->'$.note_date' <= "2018-12-31"
GROUP BY sname, cat_name;

DROP TEMPORARY TABLE IF EXISTS jsonTemporary;