Get `Sum of` from two different join(Includes) in Sequelize - mysql

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);
})

Related

I try to make a Daily Gamble Game however

I try to get the Highest Number out of my Databse.
So far so good Test 1 Code:
const db = require("../../../database.js")
const test = require("./test.js")
module.exports = {
config: {
name: "try",
description: "Replies with a Number.",
},
permissions: ['SendMessages'],
owner: false,
run: async (client, message, args, prefix) => {
const test = await db.query("select Number, MemberID from numbers order by Number DESC LIMIT 3;")
console.log(test[1])
console.log(test[1].Number)
}}
But all I get out in my Console is:
Executing (default): select Number, MemberID from numbers order by Number DESC LIMIT 3;
[ { Number: 138, MemberID: '318735407963439104' } ]
undefined
So I tried another Version:
const db = require("../../../database.js")
module.exports = {
config: {
name: "stats",
description: "Replies with a Number.",
},
permissions: ['SendMessages'],
owner: false,
run: async (client, message, args, prefix) => {
const query = await db.query("select Number, MemberID from numbers order by Number DESC LIMIT 3;", async function (err, result, fields)
{
console.log(query)
const level = result[0].Number
const user = result[0].MemberID
const level1 = result[1].Number
const user1 = result[1].MemberID
const level2 = result[2].Number1
const user2 = result[2].MemberID
console.log(level)
})
}
};
But this just showed this in the Console
Executing (default): select Number,MemberID from numbers order by Number DESC LIMIT 3;
and nothing else.
I'm really depressed that nothing works, can someone help?

How can I convert this data set into an object

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()

Create a dynamic Mysql Insert from an Object

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.

Fetch all records from table A where id = somvalue in B plus records which don't have id in B

I have two tables a coupons table and a coupon_city_map table.
id
coupon_code
1
OFFER20
2
OFFER10
3
OFFER50
4
OFFER40
5
OFFER90
coupon_Id
city_id
1
2
2
3
3
4
4
2
I need coupons with ids 1 4, and 5 for city_id = 2.
So It should fetch all the coupons where city_id=2 i.e. coupons with id 1 and 4
and it should also fetch coupons which don't have key in coupon_city_map i.e 5.
This is what I have tried but the query in [Op.or] is not working, and it returns all the coupons instead.
let coupons = await Coupon.findAll({
where: {
[Op.or]: [
{ '$CouponCities.city_id$': city_id },
{ '$CouponCities.coupon_id$': null },
],
...filters // other filter like is_active: true
},
include: {
model: CouponCity,
attributes: [],
},
attributes: ['id', 'coupon_code', 'discount_per', 'flat_discount', 'discount_upto', 'description', 'display'],
});
The query being generated
SELECT `Coupon`.`id`,
`Coupon`.`coupon_code`,
`Coupon`.`discount_per`,
`Coupon`.`flat_discount`,
`Coupon`.`discount_upto`,
`Coupon`.`description`,
`Coupon`.`display`
FROM `coupons` AS `Coupon`
LEFT OUTER JOIN `coupon_city_map` AS `CouponCities` ON `Coupon`.`id` = `CouponCities`.`coupon_id`
WHERE (`Coupon`.`user_id` IS NULL OR `Coupon`.`user_id` = 1)
AND `Coupon`.`is_active` = true
AND `Coupon`.`is_external` = false
AND `Coupon`.`start_date` < '2020-12-30 10:33:20'
AND `Coupon`.`expiry_date` > '2020-12-30 10:33:20';
Update
I also tried below, but still it is returning all the coupons.
let coupons = await Coupon.findAll({
// where: {
// ...filters,
// },
include: {
model: CouponCity,
required: false,
where: {
[Op.or]: [
{
zone_id: zoneId,
}, {
coupon_id: null,
},
],
},
attributes: [],
},
attributes: ['id', 'coupon_code', 'discount_per', 'flat_discount','discount_upto', 'description', 'display'],
});
...and it generates below query.
SELECT `Coupon`.`id`,
`Coupon`.`coupon_code`,
`Coupon`.`discount_per`,
`Coupon`.`flat_discount`,
`Coupon`.`discount_upto`,
`Coupon`.`description`,
`Coupon`.`display`
FROM `coupons` AS `Coupon`
LEFT OUTER JOIN `coupon_city_map` AS `CouponCities`
ON `Coupon`.`id` = `CouponCities`.`coupon_id`
AND ( `CouponCities`.`zone_id` = 1
AND `CouponCities`.`coupon_id` IS NULL )
WHERE `Coupon`.`is_active` = true
AND `Coupon`.`is_external` = false;
This is what worked for me, query is mess but it works. I am posting all the codes for better understanding for anyone interested.
Here zone is city.
{
const filters = {
start_date: {
[Op.lt]: new Date(),
},
expiry_date: {
[Op.gt]: new Date(),
},
};
if (userId) {
filters[Op.or] = [{
user_id: null,
}, {
user_id: userId,
}];
filters[Op.and] = {
[Op.or]: [
sequelize.literal('CouponZones.zone_id = 1'),
sequelize.literal('CouponZones.coupon_id IS null')
],
};
} else {
filters.user_id = null;
}
let coupons = await Coupon.findAll({
where: {
...filters,
},
include: {
model: CouponZone,
attributes: [],
},
attributes: ['id', 'coupon_code', 'discount_per', 'flat_discount', 'discount_upto', 'description', 'display'],
});
This is the query it generates.
SELECT `Coupon`.`id`,
`Coupon`.`coupon_code`,
`Coupon`.`discount_per`,
`Coupon`.`flat_discount`,
`Coupon`.`discount_upto`,
`Coupon`.`description`,
`Coupon`.`display`
FROM `coupons` AS `Coupon`
LEFT OUTER JOIN `coupon_zone_map` AS `CouponZones`
ON `Coupon`.`id` = `CouponZones`.`coupon_id`
WHERE ( `Coupon`.`user_id` IS NULL
OR `Coupon`.`user_id` = 1 )
AND ((CouponZones.zone_id = 1 OR CouponZones.coupon_id IS null))
AND `Coupon`.`is_active` = true
AND `Coupon`.`is_external` = false;
Use UNION
You can write query like below
SELECT coupons.*
FROM coupons,
coupon_city_map
WHERE coupons.id = coupon_city_map.coupon_id
AND coupon_city_map.city_id = 2
UNION
SELECT coupons.*
FROM coupons
WHERE coupons.id NOT IN(SELECT coupon_city_map.coupon_id
FROM coupon_city_map)

Ajax DataTable Sorting

Is it possible to sorting based on data inside while loop? without using the sql order by.
But also after i select which column, it will sort desc or asc based on data inside not sort by database column and limit it only 10 every page
lookup.php
$draw = $_POST['draw'];
$row = $_POST['start'];
$rowperpage = $_POST['length']; // Rows display per page
$columnIndex = $_POST['order'][0]['column']; // Column index
$columnName = $_POST['columns'][$columnIndex]['data']; // Column name
$columnSortOrder = $_POST['order'][0]['dir']; // asc or desc
$searchValue = $_POST['search']['value']; // Search value
## Custom Field value
$searchByName = $_POST['searchByName'];
$searchByGender = $_POST['searchByGender'];
$sel = $con->query("SELECT * FROM a, b WHERE a.nrek=b.nrek GROUP BY a.name");
$records = $con->num_rows();
$totalRecords = $records;
## Total number of records with filtering
$sel = $con-query("SELECT * FROM a, b WHERE a.nrek=b.nrek AND 1 ".$searchQuery."GROUP BY a.name");
$records = $con->num_rwos();
$totalRecordwithFilter = $records;
$empQuery = $con->query("SELECT * FROM a, b, c WHERE a.nrek=b.nrek AND a.kode=c.kode AND a.kode='3' GROUP BY a.nrek ORDER BY ".$columnName." ".$columnSortOrder." limit ".$row.",".$rowperpage");
while ($row1 = $empquery->fetch_array())
{
$querybalance2 = $con->query("SELECT SUM(b.balance) as balance FROM a JOIN a ON a.nrek= b.nrek WHERE a.kode= '$row1[kode]' AND b.period='$_SESSION[lastperiod]'");
$querybalance2 = $con->query("SELECT SUM(b.balance) as balance FROM a JOIN a ON a.nrek= b.nrek WHERE a.kode= '$row1[kode]' AND b.period='$_SESSION[newperiod]'");
$balance2 = $querybalance2->fetch_array();
$balance1 = $querybalance1->fetch_array();
$data[] = array(
"arek"=>$row1[nrek],
"balance1"=>$balance1,
"balance2"=>$balance2
);
}
$response = array(
"draw" => intval($draw),
"iTotalRecords" => $totalRecords,
"iTotalDisplayRecords" => $totalRecordwithFilter,
"aaData" => $data
);
echo json_encode($response);
Ajax.js
var dataTable = $('#empTable').DataTable
({
'processing': true,
'serverSide': true,
'serverMethod': 'post',
//'searching': false, // Remove default Search Control
'ajax':
{
'url':'lookup.php',
'data': function(data)
{
}
},
'columns':
[
{ data: 'arek' },
{ data: 'balance1', className: 'text-center' },
{ data: 'balance2', className: 'text-center' },
]
});
html.php
<table id="empTable" class="display dataTable">
<thead>
<tr>
<th>Nrek</th>
<th>Balance1</th>
<th>Balance2</th>
</tr>
</thead>
</table>
I want to limit it so the data will load and display faster. If user click on the column, datatable will sort it based on data not column. I tried but "invalid json response", because there isn't "balance2" column in database.
Need help and thank you