Is there a more efficient method than running several database queries to generate a JSON object?

I've been tackling this code and wondering if there's a sleeker way to handle it. As it stands, the code is starting to become unruly, resembling a tangled mess. This specific code snippet involves MariahDB + Express.

app.get

("/ordersInfo", function (req, res) {
  connection.query("SELECT SUM(`subtotal`) as data FROM `orders` WHERE created_at BETWEEN '" + moment().startOf("day").format() + "' AND '" + moment().endOf("day").format() + "'", (err, dailyTotalRevenue) => {
    connection.query("SELECT SUM(`subtotal`) as data FROM `orders` WHERE created_at BETWEEN '" + moment().startOf("week").format() + "' AND '" + moment().endOf("week").format() + "'", (err, weeklyTotalRevenue) => {
      connection.query("SELECT SUM(`subtotal`) as data FROM `orders` WHERE created_at BETWEEN '" + moment().startOf("month").format() + "' AND '" + moment().endOf("month").format() + "'", (err, monthlyTotalRevenue) => {
        connection.query("SELECT COUNT(*) as data FROM `orders` WHERE created_at BETWEEN '" + moment().startOf("day").format() + "' AND '" + moment().endOf("day").format() + "'", (err, dailyTotalOrderCount) => {
          connection.query("SELECT COUNT(*) as data FROM `orders` WHERE created_at BETWEEN '" + moment().startOf("week").format() + "' AND '" + moment().endOf("week").format() + "'", (err, weeklyTotalOrderCount) => {
            connection.query("SELECT COUNT(*) as data FROM `orders` WHERE created_at BETWEEN '" + moment().startOf("month").format() + "' AND '" + moment().endOf("month").format() + "'", (err, monthlyTotalOrderCount) => {
              connection.query("SELECT * FROM `orders` WHERE created_at BETWEEN '" + moment().startOf("month").format() + "' AND '" + moment().endOf("month").format() + "'", (err, month) => {
                connection.query("SELECT COUNT(*) as data FROM `orders` WHERE status = 'pending'", (err, totalPending) => {
                  connection.query("SELECT COUNT(*) as data FROM `orders` WHERE status = 'ready_to_ship'", (err, totalReadyToShip) => {
                    if (err) {
                      console.log(err);
                      res.json({ error: true });
                    } else {
                      return res.json({
                        daily: {
                          totalRevenue: (dailyTotalRevenue[0].data) ? dailyTotalRevenue[0].data : 0,
                          totalOrderCount: (dailyTotalOrderCount[0].data) ? dailyTotalOrderCount[0].data : 0,
                        },
                        weekly: {
                          totalRevenue: (weeklyTotalRevenue[0].data) ? weeklyTotalRevenue[0].data : 0,
                          totalOrderCount: (weeklyTotalOrderCount[0].data) ? weeklyTotalOrderCount[0].data : 0,
                        },
                        monthly: {
                          totalRevenue: (monthlyTotalRevenue[0].data) ? monthlyTotalRevenue[0].data : 0,
                          totalOrderCount: (monthlyTotalOrderCount[0].data) ? monthlyTotalOrderCount[0].data : 0,
                        },
                        total: {
                          totalPending: totalPending[0].data,
                          totalReadyToShip: totalReadyToShip[0].data,
                        }
                      });
                    }
                  });
                });
              });
            });
          });
        });
      });
    });
  });
});

The outcome appears as shown in this image:

https://i.sstatic.net/I3M7f.png

While the current setup gets the job done, I'm anticipating needing additional information from that same database table. Is there a more streamlined and effective way to tackle this?

Answer №1

If you combine the separate queries, it can be refactored into a single query like this:

select sum(case when DATE(created_at) = CURDATE() then subtotal end) as dailyTotalRevenue,
       sum(case when YEARWEEK(created_at, 1) = YEARWEEK(CURDATE(), 1) then subtotal end) as weeklyTotalRevenue,
       count(case when status = 'pending' then 1 end) as pendingCount,
       count(case when status = 'ready_to_ship' then 1 end) as readyToShipCount
from orders

The table data shown here: https://i.sstatic.net/2ZKKN.png

In the example (today is 2021-02-14): https://i.sstatic.net/lDF3K.png

To learn more: Is it possible to specify condition in Count()?

Note that an additional argument (1) is added to the YEARWEEK function to set Monday as the start of the week.

Answer №2

If you want to improve the readability and cleanliness of your code, using a promise chain is a great option. Here's a pseudocode example to illustrate how it can be done:

Firstly, create a function for querying the database:

function QueryDatabase(queryString) {
  return new Promise((resolve, reject) => {
    connection.query(queryString, (err, data) => {
      if (err) reject(err.message);
      resolve(data);
    });
  });
}

You can then chain these functions together like so:

QueryDatabase(qs1).then(data => QueryDatabase(qs2)).then(data => QueryDatabase(qs3))./*continue chaining as needed*/.catch(error => console.log(error))

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error in public build of Gatsby & Contentful site due to incorrect file paths

Encountering difficulties while attempting to deploy a Gatsby site with Contentful CMS. Development mode runs smoothly, but issues arise during the build process. Upon executing the Gatsby build command, the site is deployed successfully initially. Howeve ...

Divide a single array into two separate arrays using React Native

My goal is to divide an array into two separate arrays, one for letters and the other for frequencies. var list = [ "ES 324798", "LE 237076", "EN 231193" ] This is the original array that needs to be split. I am looking to create an array with all the l ...

Error: Unable to assign value to property 12 because the object does not support extensibility

I'm facing an issue with my client application as I cannot figure out the error I am encountering. Despite successfully subscribing to a GraphQL subscription and receiving updates, I am struggling to update the TypeScript array named "models:ModelClas ...

Glass-pane or angular/HTML overlay on a designated element

Is there a way to create a glass-pane effect, like an hourglass symbol on a semi-transparent layer, within the boundaries of an HTML element E? The goal is to have the glass-pane only overlap the area within E's boundaries. When the glass-pane is ac ...

Creating a three.js visualization of a cheerful X-Y coordinate graph

I am looking to generate a positive X-Y plane in mesh format using three.js. Additionally, I would like the ability to click on any intersection point and retrieve the coordinate values, resembling a graph paper layout. Design.prototype.mouseUp = functi ...

Verify that the length of all input fields is exactly 7 characters

My task involves checking the length of multiple input fields that share a common class. The goal is to verify that all fields have a length of 7. After attempting a solution, I encountered an issue where even if the length of all fields is indeed 7, the ...

Localization of labels and buttons in Angular Owl Date Time Picker is not supported

When using the Owl Date Time Picker, I noticed that the From and To labels, as well as the Set and Cancel buttons are not being localized. Here is the code snippet I am using to specify the locale: constructor( private dateTimeAdapter: DateTimeAdapter&l ...

Sending a dynamic list of arguments to an AngularJS directive

Whenever I'm working on some task behind the scenes, I use a specific directive to disable buttons and prevent double submits. You can view the code for this directive here: http://jsfiddle.net/7nA3S/6/ Now, I am interested in enhancing this directiv ...

In Discord.js, the client.login() promise seems to be stuck and never resolves, causing the client.on("ready") event to never be

After creating a simple Discord bot using discord.js, I programmed it to respond with the message "Good morning to you too" whenever someone sends a message containing "good morning". Surprisingly, this feature worked seamlessly until recently when the bot ...

Require help with personalizing a jQuery horizontal menu

I recently downloaded this amazing menu for my first website project By clicking the download source link, you can access the code Now, I need your kind help with two issues: Issue 1: The menu seems to be getting hidden under other elements on the page ...

I wonder where the file from the HTML form download has originated

Recently, I've been experimenting with the developer tools in Chrome to observe the behavior of websites at different moments. It has proven useful in automating certain tasks that I regularly perform. Currently, my focus is on automating the process ...

Is there a way for me to control the permissions granted to jhipster's authorities?

In the process of developing a web application with JHipster code generator, I have extended the pre-existing roles to a total of 5: ROLE_USER, ROLE_ADMIN, ROLE_ANONYMOUS, ROLE_PRESIDENT, ROLE_VICE_PRESIDENT I am now seeking guidance on how to manage per ...

function for ajax response is received

How can I replace HTML code with the 'for from django' function using a jQuery AJAX call? $.ajax({ url: url, data: ...

AngularJS disrupts the JSON data format

Upon receiving data from the server in JSON format, I have noticed that it is not displaying in the expected order: [{ "outlet_id": 83, "outlet_name": "My Outlet", "address": "My Outlet", "shop_number": "123", "street": "123", "building_no": ...

Sequential execution of the .then statements is not occurring

I am currently working on a Node.js/Express application. In my code, I have implemented a promise to check for the existence of an email in my PostGres database: //queries.js const checkEmail = function(mail) { return new Promise(function(resolve, rejec ...

The Next.js developer encounters an issue where the build fails due to a ReferenceError on a client component, stating that "window

Just starting out with nextjs, I'm sticking to using only the basic features without diving into any advanced functionalities. During the next build process, I encountered an issue where 6 paths failed because of a ReferenceError: window is not defin ...

Achieving compatibility between Select2 Gem and ActiveAdmin "New" Button

I have a Ruby on Rails application that utilizes the ActiveAdmin and Select2 Gems. Currently, I have implemented a search box that displays potential options from the provided set after typing two letters. The code for this feature is as follows: f.has_ma ...

Issue with Three.js GLTF loader peculiar behavior while attempting to incorporate three-dimensional text

I had an idea to import a prebuilt gltf scene created in Blender, then add some 3D text using the ttf loader and manipulate it. Each loader worked perfectly when used separately, but strange things started happening when I combined them into a single scrip ...

How can I retrieve the value of a JavaScript variable using Ajax?

Hello everyone! I've been a long-time user of various programming forums, but this is my first time posting. Lately, I created a really simple browser-based game, and when I say simple, I mean it's incredibly basic. The whole game logic resides ...

The value of Vue.js props appears as undefined

It appears that I may be misunderstanding how props work, as I am encountering difficulty passing a prop to a component and retrieving its value, since it always shows up as undefined. Route: { path: '/account/:username', name: 'accco ...