在JavaScript中SQL连接两个或多个数组

时间:2016-05-26 15:03:41

标签: javascript sql arrays

我有一个页面很少的网页应用程序,这些数组在逻辑上是链接的:来自"用户"是指" user_types"," charge"是指"用户"等:

var users = [
    { id:   "u0001", name: "John",      user_type_id: "1" },
    { id:   "u0002", name: "Bob",       user_type_id: "1" },
    { id:   "u0003", name: "Alice",     user_type_id: "5" },
    { id:   "u0004", name: "Jennifer",  user_type_id: "5" },
    // ... more
];

var user_types = [
    { id: "1", name: "Regular Clients"},
    { id: "5", name: "VIP Clients"},
    // ... more
];

var charges = [
    { id: "7443", user_id: "u0001", date: "2016-01-01", amount: "3.99", },
    { id: "7445", user_id: "u0001", date: "2016-01-01", amount: "4.02", },
    { id: "7448", user_id: "u0001", date: "2016-01-01", amount: "6.99", },
    { id: "7453", user_id: "u0003", date: "2016-01-01", amount: "3.00", },
    { id: "7469", user_id: null   , date: "2016-01-01", amount: "3.99", },
    // ... more
];

我需要以链接的方式显示它们,类似于以下SQL的产品:

SELECT 
     charges.date, 
     charges.amount, 
     users.name, 
     user_types.name
FROM 
     charges
          LEFT OUTER JOIN users ON users.id = charges.user_id
          LEFT OUTER JOIN user_types ON user_types.id = users.user_type_id

我知道我可以在服务器上使用此SQL查询创建API调用,但我想避免这种情况,因为表已经加载到Web应用程序中。

在内存中加入它们的最简单方法是什么?

5 个答案:

答案 0 :(得分:1)

如果您可以修改usersuser_types的填充方式,那么您可以很快完成此操作。

您需要将usersuser_types更改为对象,以便您拥有以下内容:



// make users an object with the id as the key
var users = {
	"u0001" : { name: "John",      user_type_id: "1" },
	"u0002" : { name: "Bob",       user_type_id: "1" },
	"u0003" : { name: "Alice",     user_type_id: "5" },
	"u0004" : { name: "Jennifer",  user_type_id: "5" }
};

// same for user_types
var user_types = {
	"1" : { name: "Regular Clients" },
	"5" : { name: "VIP Clients" }
};

var charges = [
	{ id: "7443", user_id: "u0001", date: "2016-01-01", amount: "3.99", },
	{ id: "7445", user_id: "u0001", date: "2016-01-01", amount: "4.02", },
	{ id: "7448", user_id: "u0001", date: "2016-01-01", amount: "6.99", },
	{ id: "7453", user_id: "u0003", date: "2016-01-01", amount: "3.00", },
	{ id: "7469", user_id: null   , date: "2016-01-01", amount: "3.99", }
];

// now you can just loop through and use object key lookups:

var out = [];

for(var i = 0, numCharges = charges.length; i < numCharges; ++i)
{
	var currentCharge = charges[i];
	
	if(currentCharge.user_id === null) continue;
	
	out.push([
		currentCharge.date,
		currentCharge.amount,
        
        // get the current charges user_id and look up the name from users
		users[currentCharge.user_id].name,
        
        // same as above but use the user_type_id to get the user_type name
		user_types[users[currentCharge.user_id].user_type_id].name
	]);
}

console.log(out);
&#13;
&#13;
&#13;

答案 1 :(得分:1)

如果小型库可以,可以使用StrelkiJS

完成
config.active_record.raise_in_transactional_callbacks = true

结果将加入以下结构数组:

var users = new StrelkiJS.IndexedArray();
users.loadArray([
        { id:   "u0001", name: "John",      user_type_id: "1" },
        { id:   "u0002", name: "Bob",       user_type_id: "1" },
        { id:   "u0003", name: "Alice",     user_type_id: "5" },
        { id:   "u0004", name: "Jennifer",  user_type_id: "5" },
        // ... more
    ]);
var user_types = new StrelkiJS.IndexedArray();
user_types.loadArray([
        { id: "1", name: "Regular Clients"},
        { id: "5", name: "VIP Clients"},
        // ... more
    ]);
var charges = new StrelkiJS.IndexedArray();
charges.loadArray([
        { id: "7443", user_id: "u0001", date: "2016-01-01", amount: "3.99", },
        { id: "7445", user_id: "u0001", date: "2016-01-01", amount: "4.02", },
        { id: "7448", user_id: "u0001", date: "2016-01-01", amount: "6.99", },
        { id: "7453", user_id: "u0003", date: "2016-01-01", amount: "3.00", },
        { id: "7469", user_id: null   , date: "2016-01-01", amount: "3.99", },
        // ... more
    ]);

var result = charges.query([{
    from_col: "user_id",
    to_table: users,
    to_col: "id",
    type: "outer",
    join: [{
        from_col: "user_type_id",
        to_table: user_types,
        to_col: "id",
        type: "outer",
    }]
}])

答案 2 :(得分:1)

此提案采用IMTheNachoMan解决方案,扩展了来自给定数据的生成必需对象。

它包含charges所有行,因为使用SQL时,也会返回行。

此处测试null值的问题,然后返回null

&#13;
&#13;
var users = [{ id: "u0001", name: "John", user_type_id: "1" }, { id: "u0002", name: "Bob", user_type_id: "1" }, { id: "u0003", name: "Alice", user_type_id: "5" }, { id: "u0004", name: "Jennifer", user_type_id: "5" }],
    user_types = [{ id: "1", name: "Regular Clients" }, { id: "5", name: "VIP Clients" }],
    charges = [{ id: "7443", user_id: "u0001", date: "2016-01-01", amount: "3.99", }, { id: "7445", user_id: "u0001", date: "2016-01-01", amount: "4.02", }, { id: "7448", user_id: "u0001", date: "2016-01-01", amount: "6.99", }, { id: "7453", user_id: "u0003", date: "2016-01-01", amount: "3.00", }, { id: "7469", user_id: null, date: "2016-01-01", amount: "3.99", }],
    user = Object.create(null),
    type = Object.create(null),
    result;

users.forEach(function (u) {
    user[u.id] = u;
});

user_types.forEach(function (t) {
    type[t.id] = t;
});

result = charges.map(function (charge) {
    return {
        'charges.date': charge.date,
        'charges.amount': charge.amount,
        'users.name': charge.user_id === null ? null : user[charge.user_id].name,
        'user_types': charge.user_id === null ? null : type[user[charge.user_id].user_type_id].name,
    };
});

console.log(result);
&#13;
&#13;
&#13;

答案 3 :(得分:0)

制作users地图,以便您使用users['u0001']。然后循环浏览charges并执行users[current_charge.user_id].charges.push(current_charge)users中的每个用户都应将charges属性初始化为空数组。将users数组转换为id => user地图时,可以执行此操作。

此处您不需要任何特殊内容,只需通过userscharges两个循环:

var users_map = {};
var i;
for(i = 0; i < users.length; i++) {
    users_map[users[i].id] = users[i];
    users_map[users[i].id].charges = [];
}

for(i = 0; i < charges.length; i++) {
    users_map[charge[i].user_id].charges.push(charge[i]);
}

如果您确实需要最终的“结果”作为数组而不是地图,则可以再次遍历users_map并将其转换为数组。 一个非常简单的解决方案利用现代JS的东西是这样的:

var joined_data = Object.keys(users_map).map(function (key) {
    return users_map[key];
});

您可以使用lodash或其他类似的库使上述代码更漂亮。

答案 4 :(得分:0)

在不重构对象的情况下执行此操作的唯一方法是循环和过滤。 您可以通过首先处理用户及其类型来稍微优化它,但这就是它......

var users = [
    { id:   "u0001", name: "John",      user_type_id: "1" },
    { id:   "u0002", name: "Bob",       user_type_id: "1" },
    { id:   "u0003", name: "Alice",     user_type_id: "5" },
    { id:   "u0004", name: "Jennifer",  user_type_id: "5" },
    // ... more
];

var user_types = [
    { id: "1", name: "Regular Clients"},
    { id: "5", name: "VIP Clients"},
    // ... more
];

var charges = [
    { id: "7443", user_id: "u0001", date: "2016-01-01", amount: "3.99", },
    { id: "7445", user_id: "u0001", date: "2016-01-01", amount: "4.02", },
    { id: "7448", user_id: "u0001", date: "2016-01-01", amount: "6.99", },
    { id: "7453", user_id: "u0003", date: "2016-01-01", amount: "3.00", },
    { id: "7469", user_id: null   , date: "2016-01-01", amount: "3.99", },
    // ... more
];

// pre-process users
var usersPlusTypes = users.map(function(u) {
  var foundUserTypes = user_types.filter(function(ut) {
    return ut.id == u.user_type_id;
  });

  return {
    id: u.id,
    user: u,
    userType: foundUserTypes.length ? foundUserTypes[0] : null
  }
})

// now link charges to users
var results = charges.map(function(c) {
  var user = usersPlusTypes.filter(function(upt) {
    return upt.id == c.user_id;
  });
  
  return {
    date: c.date,
    amount: c.amount,
    userName: user.length ? user[0].user.name : null,
    userTypeName: user.length && user[0].userType ? user[0].userType.name : null,
  };
});

console.log(results);