I would like to convert this data set into an object.
Intended outcome
let data = [
{
"Year Group": "Year Six",
"Sunday": [Girl's football],
"Monday": [No clubs on this day],
"Tuesday": [Girls Netball]
},
{
"Year Group": "Year Five",
"Sunday": [Boys football],
"Monday": [No clubs on this day],
"Tuesday": [Girls Netball]
}
]
This data will then be used to create a branching Google form. If there is a better object structure in order to achieve this, please do let me know.
Thank you,
For those that may need it. Following one of the answers, I realised it would be better if I had a situation where only the days unique to the year group were stored in the year group object.
Below is the adapted code based on one of the answers by 'TheWizEd'.
let values = ws.getDataRange().getValues();
let data = [];
values.shift(); // remove headers
// create year groups
let yearGroups = [...new Set(values.map( row => row[1] ))];
yearGroups.forEach((group) => {
let sorted = values.filter( row => row[1] === group )
let days = [...new Set(sorted.map((row)=> row[4] ))]
let dayBlankArray = days.map( day => [] )
sorted.forEach((e)=>{
let index = days.indexOf(e[4]);
if( index >= 0 ) dayBlankArray[index].push(e[0]);
})
let object = { "Year Group": group };
days.forEach((day,index)=> {
object[day] = dayBlankArray[index]
})
data.push(object);
})
return data
}
Here is an example of how to sort and create groups by year.
Code.gs
function createGroups() {
try {
let days = ["Sunday","Monday","Tuesday","Wednesday"];
let spread = SpreadsheetApp.getActiveSpreadsheet();
let sheet = spread.getSheetByName("Sheet1");
let values = sheet.getDataRange().getValues();
let data = [];
values.shift(); // remove headers
// create year groups
let groups = [...new Set(values.map( row => row[1] ))];
console.log("groups = "+groups)
groups.forEach( group => {
let activities = days.map( day => [] );
// sort by group
let sorted = values.filter( row => row[1] === group );
// nest sort by day
sorted.forEach( activity => {
let index = days.indexOf(activity[4]);
if( index >= 0 ) activities[index].push(activity[0]);
}
);
// now construct the object
let object = { "Year Group": group };
let numDays = days.length;
days.forEach( (day,index) => {
if( activities[index].length === 0 ) {
activities[index].push("No clubs on this day");
numDays--;
}
object[day] = activities[index];
}
);
object["Num Days"] = numDays;
data.push(object);
}
);
console.log(data);
}
catch(err) {
console.log(err)
}
}
Execution log
9:34:27 AM Notice Execution started
9:34:28 AM Info groups = Year Five,Year Six,Year Seven,Year One,Year Two
9:34:28 AM Info [ { 'Year Group': 'Year Five',
Sunday: [ 'Girls Football', 'Boys Football' ],
Monday: [ 'No clubs on this day' ],
Tuesday: [ 'Girls Netball' ],
Wednesday: [ 'No clubs on this day' ] },
{ 'Year Group': 'Year Six',
Sunday: [ 'Girls Football' ],
Monday: [ 'No clubs on this day' ],
Tuesday: [ 'Girls Netball' ],
Wednesday: [ 'No clubs on this day' ] },
{ 'Year Group': 'Year Seven',
Sunday: [ 'Girls Football', 'Boys Football' ],
Monday: [ 'No clubs on this day' ],
Tuesday: [ 'Girls Netball' ],
Wednesday: [ 'No clubs on this day' ] },
{ 'Year Group': 'Year One',
Sunday: [ 'No clubs on this day' ],
Monday: [ 'No clubs on this day' ],
Tuesday: [ 'Multi Sports' ],
Wednesday: [ 'Gymnastics' ] },
{ 'Year Group': 'Year Two',
Sunday: [ 'No clubs on this day' ],
Monday: [ 'No clubs on this day' ],
Tuesday: [ 'Multi Sports' ],
Wednesday: [ 'Gymnastics' ] } ]
9:34:28 AM Notice Execution completed
Reference
Array.map()
[...new Set()]
Array.forEach()
Array.filter()
Array.indexOf()
Related
I have a project in Typescript in which I am trying to create an Insert through the options that I send through an object. Right now I have two objects, one for each Insert, these Inserts are created in different tables and with different objects. I would like to know if it is possible to create a general Insert for several objects.
This is what I currently have:
let object1 = [
{ country: 'CO', name: 'CO_SE.xml', exists: 1 },
{ country: 'CO', name: 'CO_IN.xml', exists: 1 },
{ country: 'CO', name: 'CO_BR.xml', exists: 1 }
];
`INSERT INTO ${database} VALUES` + object1.map((elem: any) =>
`"${elem.country}", "${elem.name}", ${elem.exists})`).join(', ');
let object2 = [
{ code: 1, folder: '/ToFtp', max: 8 },
{ code: 2, folder: '/ToXml', max: 5 },
{ code: 3, folder: '/ToMail', max: 5 }
];
`INSERT INTO ${database} VALUES` + object2.map((elem: any) =>
`${elem.code}, "${elem.folder}", ${elem.max})`).join(', ');
This is what I am trying to achieve:
let object1 = [
{ country: 'CO', name: 'CO_SE.xml', exists: 1 },
{ country: 'CO', name: 'CO_IN.xml', exists: 1 },
{ country: 'CO', name: 'CO_BR.xml', exists: 1 }
];
let object2 = [
{ code: 1, folder: '/ToFtp', max: 8 },
{ code: 2, folder: '/ToXml', max: 5 },
{ code: 3, folder: '/ToMail', max: 5 }
];
`INSERT INTO ${database} VALUES` + ${object}.map((elem: any) =>
`"${elem.elem1}", ... ${elem.elemN})`).join(', ');
Is this possible? I'm not sure this can be done.
You can create methods to prepare your query and values. You can do something like this.
let object1 = [
{ country: 'CO', name: 'CO_SE.xml', exists: 1 },
{ country: 'CO', name: 'CO_IN.xml', exists: 1 },
{ country: 'CO', name: 'CO_BR.xml', exists: 1 }
];
function getValues<T extends Record<string, any>[]>(obj: T) {
const values = obj.map((item) => {
const val = Object.values(item).map((v) => v);
return val;
});
return values;
}
function getColumns<T extends Record<string, any>>(obj: T) {
return Object.keys(obj);
}
function getFilters<T extends Record<string, any>>(obj: T) {
const constraints: string[] = [];
const queryArray: any[] = [];
Object.entries(obj).forEach(([k, v]) => {
constraints.push(`${k} = ?`);
queryArray.push(v);
});
return {
constraints,
queryArray
}
}
const columns = getColumns(object1[0]);
const values = getValues(object1);
const sql = `INSERT INTO MyTable(${columns.join(", ")}) VALUES ?`;
const filters = {
country: "CO"
};
const selectFilters = getFilters(filters);
const selectSql = `SELECT ${columns} FROM MyTable WHERE ${selectFilters.constraints.join(" AND ")}`;
console.log(columns); // [ 'country', 'name', 'exists' ]
console.log(sql); // INSERT INTO MyTable(country, name, exists) VALUES ?
console.log(values); // [ [ 'CO', 'CO_SE.xml', 1 ], [ 'CO', 'CO_IN.xml', 1 ], [ 'CO', 'CO_BR.xml', 1 ] ]
// now you can use something like this
connection.query({ sql, values });
Note: Make sure you sanitize your input before using these functions to avoid any damage you may create if your input is not as you are expecting it.
I want to get sum of column from two different tables in sequilize.
I want to accurate totalpaid, refunded & refundable field, which vary according to group by, I'm not be able to resolve it.
//Some pre-desined variables
var totalPaidQueryStr = '(CASE WHEN (SUM(inv_payment_record_invoices.payment)) IS NULL THEN 0 ELSE (SUM(inv_payment_record_invoices.payment)) END)';
var totalPaidQuery = [Sequelize.literal(totalPaidQueryStr), 'totalpaid']; //Get the total paid amount till date;
var refundedQueryStr = '(CASE WHEN (SUM(inv_payment_record_refunds.amount)) IS NULL THEN 0 ELSE (SUM(inv_payment_record_refunds.amount)) END)';
var refundedQuery = [Sequelize.literal(refundedQueryStr), 'refunded']; //Get the total paid amount till date
var refundableQueryStr = `(inv_payment_records.amount - (${totalPaidQueryStr} + ${refundedQueryStr}))`;
var refundableQuery = [Sequelize.literal(refundableQueryStr), 'refundable']; //Get the total due amount
return InvPaymentRecords.findOne({
attributes: [
'customer_id',
'amount',
'company_currency_id',
'exchange_rate',
totalPaidQuery, //Want to accurate sum
refundedQuery, //Want to accurate sum
refundableQuery
],
where: {
'id': payment_record_id,
'company_id': company_id
},
include: [
{
model: InvPaymentRecordInvoices,
require: false,
attributes: [],
},
{
model: InvPaymentRecordRefund,
require: false,
attributes: [],
}
],
group: [
//'inv_payment_records.id',
//'inv_payment_record_invoices.id',
//'inv_payment_record_refunds.id'
]
}).then(iprdata => {
return sequelize.Promise.resolve(iprdata);
}).catch(error => {
return sequelize.Promise.reject(error);
})
I have to tables - one for events and another one for the dates (start-end) this event is "active".
id name
-- ----
1 event 1
2 event 2
And then the EventDates
eventId start end
------- ----- ---
1 2018-01-14 2018-01-15
1 2018-01-17 2018-01-18
2 2018-02-14 2018-02-18
Events and EventDates are setup using hasMany()
Event.DATES = Event.hasMany(models.EventDates, {
as: 'dates',
foreignKey: 'eventId',
});
Querying for all Events including the EventDates like this:
await Event.findAll({
include: [{ association: Event.DATES }]
});
returns a nested Event list with all the EventDates - great.
[
{
id: 1,
name: 'event 1',
dates: [
{
start: '2018-01-14',
end: '2018-01-15',
},
{
start: '2018-01-17',
end: '2018-01-18',
},
],
},
{
id: 2,
name: 'event 2',
dates: [
{
start: '2018-02-14',
end: '2018-02-18',
},
],
}
]
But now I want to add a maxEndDate to an Event so I can check if it still active or if all EventDates are in the past. I can do that manually adding another LEFT JOIN like this:
# ...
LEFT OUTER JOIN (SELECT eventId, MAX(end)
FROM `EventDates`
GROUP BY eventId) dates
ON `Event`.`id` = `dates`.`eventId`
# ...
But how could I achieve the same thing with Sequelize?
[
{
id: 1,
name: 'event 1',
maxEndDate: ??,
dates: [
{
start: '2018-01-14',
end: '2018-01-15',
},
{
start: '2018-01-17',
end: '2018-01-18',
},
],
},
{
id: 2,
name: 'event 2',
maxEndDate: ??,
dates: [
{
start: '2018-02-14',
end: '2018-02-18',
},
],
}
]
It very tricky to get result with group by and has many association , but at last I found the way and here it is :
Event.findAll({
raw : true,
attributes : [ 'Event.*' , 'EventDates.eventId' , [sequelize.fn('max', sequelize.col('EventDates.end')),'end']],
include : {
model : EventDates ,
attributes :[]
},
group : ['Event.id','EventDates.eventId']
})
I think you can achieve your last out put that by this , I haven't tried this but this is the way you can go ahead
Event.findAll({
raw : true,
attributes : [ 'Event.*' , 'dates.*' , 'EventDates.eventId' , [sequelize.fn('max', sequelize.col('EventDates.end')),'end']],
include : [
{
model : EventDates ,
attributes :[]
},
{
model : EventDates ,
as : 'dates',
required : false,
separate : true
}
]
group : ['Event.id','EventDates.eventId']
})
I have a function payment_summary() as below:
CREATE OR REPLACE FUNCTION payment_summary()
RETURNS SETOF PAYMENT_SUMMARY_TYPE
LANGUAGE plpgsql
AS $$
DECLARE
payment_sum payment_summary_type%ROWTYPE;
BEGIN
FOR payment_sum IN SELECT
pay.application_no,
project.title,
pay.payment_rec,
customer.cust_name,
project.estimated_cost,
(project.estimated_cost - pay.payment_rec) AS outstanding_amt
FROM project
INNER JOIN customer
ON project.customer_cust_id = customer.cust_id
INNER JOIN
(SELECT
project.application_no,
sum(payment.amount) AS payment_rec
FROM payment
INNER JOIN project
ON payment.project_id = project.project_id
WHERE payment.drcr_flg = 'Cr'
GROUP BY project.application_no) AS pay
ON pay.application_no = project.application_no
LOOP
RETURN NEXT payment_sum;
END LOOP;
END;
$$;
PAYMENT_SUMMARY_TYPE is defined as:
CREATE TYPE PAYMENT_SUMMARY_TYPE AS
(
application_no VARCHAR(150),
title VARCHAR(500),
payment_rec INTEGER,
customer_name VARCHAR(500),
estimated_cost INTEGER,
outstanding_amt INTEGER
);
Using below code to execute the function and get results:
sequelize.query('SELECT payment_summary()').then(function(data) {
res.json(data);
});
Getting below as response:
[
[
{
"payment_summary": "(716,\"C1\",100000,\"C1 - city\",0,-100000)"
},
{
"payment_summary": "(716,\"C2\",100000,\"C2 - city\",0,-100000)"
}
],
{
"command": "SELECT",
"rowCount": 2,
"oid": null,
"rows": [
{
"payment_summary": "(716,\"C1\",100000,\"C1 - city\",0,-100000)"
},
{
"payment_summary": "(716,\"C2\",100000,\"C2 - city\",0,-100000)"
}
],
"fields": [
{
"name": "payment_summary",
"tableID": 0,
"columnID": 0,
"dataTypeID": 17453,
"dataTypeSize": -1,
"dataTypeModifier": -1,
"format": "text"
}
],
"_parsers": [
null
],
"rowAsArray": false
}
]
I need the response in below format:
[
{
application_no: 716,
title: "C1",
payment_rec : 100000,
customer_name : "C1 - city"
estimated_cost : 0
outstanding_amt : -100000
},
{
application_no: 717,
title: "C2",
payment_rec : 100000,
customer_name : "C2 - city"
estimated_cost : 0
outstanding_amt : -100000
}
]
How can i read / convert the response in required format ?
I need to write a Linq query in a specific format for a json file. There are 3 tables in the Database.
Student, with Student Id and name.
Subject, with Subject Id and name.
Results with Student Id, Student Id, Result and Date of Result.
This is my Query to get Results
var studentQuery = (from c in db.Students
join f in db.Results
on c.ID equals f.StudentID
join d in db.Subjects
on f.SubjectID equals d.ID
where c.ID == Convert.ToInt32(DropDownList1.SelectedValue)
select new newResult{
ID = f.StudentID,
Date = convertDateToUTC(f.Date.Value),
Name = c.Name.Trim(),
Result1 = f.Result1.Value,
Type = d.Subject1.Trim()
})
.ToList();
return studentQuery;
But I wish to return the query in the
in the format below
[ { "name": "Denis P6 Results", "type": "English", "data": [ [ 1325431800000, 54 ], [ 1325691000000, 65 ], [ 1325950200000, 73 ], [ 1326209400000, 60 ] ] },
{ "name": "Denis P6 Results", "type": "Maths", "data": [ [ 1325518200000, 76 ], [ 1325777400000, 81 ], [ 1326036600000, 80 ], [ 1326295800000, 70 ] ] },
{ "name": "Denis P6 Results", "type": "Science", "data": [ [ 1325604600000, 80 ], [ 1325863800000, 75 ], [ 1326123000000, 69 ], [ 1326382200000, 68 ] ] },
{ "name": "Mak P6 Results", "type": "English", "data": [ [ 1325431800000, 57 ], [ 1325691000000, 49 ], [ 1325950200000, 66 ], [ 1326209400000, 70 ] ] },
{ "name": "Mak P6 Results", "type": "Maths", "data": [ [ 1325518200000, 80 ], [ 1325777400000, 83 ], [ 1326036600000, 85 ], [ 1326295800000, 79 ] ] },
{ "name": "Mak P6 Results", "type": "Science", "data": [ [ 1325604600000, 67 ], [ 1325863800000, 69 ], [ 1326123000000, 66 ], [ 1326382200000, 62 ] ] } ]
I really need some help as I've been searching for days. I am a total newbie at this.
Thanks for any help.
Let's break this down into each of the steps you're trying to achieve:
Group the results, by person and subject.
Render these into JSON.
For the first bit, we can do something like
var groupedResults = from result in db.Results
group result by new { result.StudentID, result.SubjectID } into grouping
select new { grouping.Key, grouping };
var resultsWithName = from result in groupedResults
join student in db.Students on result.Key.StudentID equals student.ID
join subject in db.Subjects on result.Key.SubjectID equals subject.ID
select new
{
result.Key,
student.Name,
subject.Type,
result.grouping
};
resultsWithName now contains a sequence of name and subject pairs, together with a sequence of the results. This is the first bit done.
You could use a library for generating the JSON, but this isn't too bad to do by hand:
var jsonRendered = resultsWithName.Select(g =>
string.Format("{{ \"name\" : \"{0} Results\", \"type\" : \"{1}\", \"data\" : {2} }}",
g.Name,
g.Type,
"[ " + string.Join(", ", g.grouping.Select(r => string.Format("[ {0}, {1} ]", r.Date, r.Mark))) + " ]"));
Here, we iterate over all the grouped results (i.e. for each person and each subject), then create a single string containing the results for that subject.
I haven't used quite the same names for some of the variables as you, but hopefully it's clear how to adapt this for your code.
JavaScriptSerializer serializer = new JavaScriptSerializer();
var json = serializer.Serialize(resultsWithName);
Just use the built in .NET json serializer. No need to make it too complicated.